Windows 事件与跨线程调用
需求
当我们新建一个类,通常会遇到当类的一个属性变化时,如何通知用户?比如串口收到数据,tcp 或UDP 收到网络数据时,如何及时通知用户?
1、查询是否收到,若收到,在文本框显示。
2、专门新增加一个线程,专门负责接收数据。当有数据收到时,通过“数据已收到”事件,用事件处理程序,来更新文本框。
第一种方法简单,但十分占用资源。第二种方法,涉及事件及线程安全问题。
现以第二种方法为例,进行说明。
(1) 在类中声明事件处理程序
publicdelegatevoidReiceivedDataChgEventHandler(object sender,ReceivedDataChgEventArgsargs);publicReiceivedDataChgEventHandler?ReceivedDataChg;(2)在数据的set 方法中,加入事件处理
publicstringReceivedData{set{string oldValue=receivedData??"";string newValue=value??"";receivedData=value;NewData=true;OnReceivedDataChg("receivedData",oldValue,newValue);}}privatestring?receivedData;publicvirtualvoidOnReceivedDataChg(string name,object oldValue,object newValue){if(ReceivedDataChg!=null){ReceivedDataChg.Invoke(this,newReceivedDataChgEventArgs(name,oldValue,newValue));}}3、在form中,新建类,并为ReceivedDataChg增加处理程序。特别要说明的时,由于类form并不时由serialPort类创建的,由类的实例调用form中的控件时,windows 认为类越权了。所以需要由textBox2反过来调用类的事件处理程序 “setText"。
是不是有点绕。
privatevoidbutton1_Click(object sender,EventArgse){string portName=comboBox1.SelectedItemas 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");}}publicvoidSetText(object sender,ReceivedDataChgEventArgsargs){if(this.textBox2.InvokeRequired){this.textBox2.Invoke(SetText,this.textBox2,args);}else{this.textBox2.AppendText((string)args.NewValue);}}