需求
当我们新建一个类,通常会遇到当类的一个属性变化时,如何通知用户?比如串口收到数据,tcp 或UDP 收到网络数据时,如何及时通知用户?
1、查询是否收到,若收到,在文本框显示。
2、专门新增加一个线程,专门负责接收数据。当有数据收到时,通过"数据已收到"事件,用事件处理程序,来更新文本框。
第一种方法简单,但十分占用资源。第二种方法,涉及事件及线程安全问题。
现以第二种方法为例,进行说明。
(1) 在类中声明事件处理程序
java
public delegate void ReiceivedDataChgEventHandler(object sender, ReceivedDataChgEventArgs args);
public ReiceivedDataChgEventHandler? ReceivedDataChg;
(2)在数据的set 方法中,加入事件处理
java
public string ReceivedData{
set
{
string oldValue = receivedData??"";
string newValue = value??"";
receivedData = value;
NewData = true;
OnReceivedDataChg("receivedData", oldValue, newValue);
}
}
private string? receivedData;
public virtual void OnReceivedDataChg(string name, object oldValue, object newValue)
{
if (ReceivedDataChg != null)
{
ReceivedDataChg.Invoke(this, new ReceivedDataChgEventArgs(name, oldValue, newValue));
}
}
3、在form中,新建类,并为ReceivedDataChg增加处理程序。特别要说明的时,由于类form并不时由serialPort类创建的,由类的实例调用form中的控件时,windows 认为类越权了。所以需要由textBox2反过来调用类的事件处理程序 "setText"。
是不是有点绕。
java
private void button1_Click(object sender, EventArgs e)
{
string portName = comboBox1.SelectedItem as string ?? "com1";
sp = new(portName, 115200, 8, "1", SerialPortC.ParityBits.None);
sp.ReceivedDataChg += SetText;
if (sp._serialPort.IsOpen)
{
this.textBox1.Text = "AT";
sp.Writeline("AT");
}
}
public void SetText(object sender, ReceivedDataChgEventArgs args)
{
if (this.textBox2.InvokeRequired)
{
this.textBox2.Invoke(SetText, this.textBox2, args);
}
else
{
this.textBox2.AppendText((string)args.NewValue);
}
}