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

最近在写一个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窗体不在无响应,问题成功解决!

 

你可能感兴趣的:(多线程)