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窗體不在無響應,問題成功解決!

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM