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

 

posted @   景影随形  阅读(2841)  评论(0编辑  收藏  举报
编辑推荐:
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 展开说说关于C#中ORM框架的用法!
点击右上角即可分享
微信分享提示