C#多线程与UI响应 跨线程更新UI

时间:2022-08-27 21:25:07

最近在写一个TCP通信程序,自定义了一个通信类TCPclient,用于客户端异步接收和发送网络消息。

TCPclient中定义了一个接收到新的网络消息事件:

1  //收到新消息事件
2 public delegate void receiveNewNetworkMsgHandler( string networkMSG);
3 public event receiveNewNetworkMsgHandler receiveNewNetworkMsg;

在外部的窗体中订阅了此事件:

void thisClient_receiveNewNetworkMsg( string networkMSG);

起初是直接在这个函数中读取网络消息,并解析命令,然后触发窗体的LoginSuccess事件,LoginSuccess事件的委托函数会New一个 main 窗体

但是问题是这个new的main窗体总是无响应。

经过很长时间的摸索,终于得出以下结论

在自定义类中定义并触发事件,那么UI中的事件处理代码也就工作在自定义类线程中,访问UI中控件需要invoke
在此之前,我一直认为事件处理函数在哪个类,自然运行的时候就在相应的线程中执行,至此才明白错在哪里。

根据这条结论,自然就不能直接在thisClient_receiveNewNetworkMsg函数中直接进行命令的解析以及触发LoginSuccess事件,

所以现在在thisClient_receiveNewNetworkMsg函数中进行如下更改:

1         public delegate void NetMsgDealHandler(string str);
2         void thisClient_receiveNewNetworkMsg( string networkMSG) 
4         {
5             NetMsgDealHandler newMSG = new NetMsgDealHandler(NetMsgDeal);
6             BeginInvoke(newMSG, networkMSG);
7         }
 1         void NetMsgDeal(string networkMSG) {
 2             XmlDocument xmldoc = new XmlDocument();
 3             try { xmldoc.LoadXml(networkMSG); }
 4             catch (Exception ex) { MessageBox.Show(string.Format("XML加载错误({1}):{0}", networkMSG, ex.Message)); return; }
 5             XmlElement rootElement = xmldoc.ChildNodes[0] as XmlElement;
 6             XmlElement SecElement = rootElement.ChildNodes[0] as XmlElement;
 7             switch (SecElement.Name) {
 8                 case "login": {
10                         if (SecElement.SelectSingleNode("cmd").InnerText == "2") {
11                             if (SecElement.SelectSingleNode("isSuccess").InnerText == "True") {
12                                 //触发LoginSuccess事件
13                                 this.loginSuccess(this);
14                             }
15                             else {
16                                 //触发loginFailed事件
17                                 this.LoginFailed(this);
18                             }
19                         }
21                     } break;22                 //此处省略若干行
23                 default: { MessageBox.Show(string.Format("得到无法处理的消息:{0}", networkMSG)); return; }
24             }
25         }

现在再次执行main窗体不在无响应,问题成功解决!