C#多线程与UI响应 跨线程更新UI
最近在写一个TCP通信程序,自定义了一个通信类TCPclient,用于客户端异步接收和发送网络消息。
TCPclient中定义了一个接收到新的网络消息事件:
//收到新消息事件
public delegate void receiveNewNetworkMsgHandler( string networkMSG);
public event receiveNewNetworkMsgHandler receiveNewNetworkMsg;
在外部的窗体中订阅了此事件:
void thisClient_receiveNewNetworkMsg( string networkMSG);
起初是直接在这个函数中读取网络消息,并解析命令,然后触发窗体的LoginSuccess事件,LoginSuccess事件的委托函数会New一个 main 窗体
但是问题是这个new的main窗体总是无响应。
经过很长时间的摸索,终于得出以下结论
在自定义类中定义并触发事件,那么UI中的事件处理代码也就工作在自定义类线程中,访问UI中控件需要invoke
在此之前,我一直认为事件处理函数在哪个类,自然运行的时候就在相应的线程中执行,至此才明白错在哪里。
根据这条结论,自然就不能直接在thisClient_receiveNewNetworkMsg函数中直接进行命令的解析以及触发LoginSuccess事件,
所以现在在thisClient_receiveNewNetworkMsg函数中进行如下更改:
public delegate void NetMsgDealHandler(string str);
void thisClient_receiveNewNetworkMsg( string networkMSG)
{
NetMsgDealHandler newMSG = new NetMsgDealHandler(NetMsgDeal);
BeginInvoke(newMSG, networkMSG);
}
void NetMsgDeal(string networkMSG) {
XmlDocument xmldoc = new XmlDocument();
try { xmldoc.LoadXml(networkMSG); }
catch (Exception ex) { MessageBox.Show(string.Format("XML加载错误({1}):{0}", networkMSG, ex.Message)); return; }
XmlElement rootElement = xmldoc.ChildNodes[] as XmlElement;
XmlElement SecElement = rootElement.ChildNodes[] as XmlElement;
switch (SecElement.Name) {
case "login": {
if (SecElement.SelectSingleNode("cmd").InnerText == "") {
if (SecElement.SelectSingleNode("isSuccess").InnerText == "True") {
//触发LoginSuccess事件
this.loginSuccess(this);
}
else {
//触发loginFailed事件
this.LoginFailed(this);
}
}
} break; //此处省略若干行
default: { MessageBox.Show(string.Format("得到无法处理的消息:{0}", networkMSG)); return; }
}
}
现在再次执行main窗体不在无响应,问题成功解决!
C#多线程与UI响应 跨线程更新UI的更多相关文章
- (转).NET 4.5中使用Task.Run和Parallel.For()实现的C# Winform多线程任务及跨线程更新UI控件综合实例
http://2sharings.com/2014/net-4-5-task-run-parallel-for-winform-cross-multiple-threads-update-ui-dem ...
- C# Winform 跨线程更新UI控件常用方法汇总(多线程访问UI控件)
概述 C#Winform编程中,跨线程直接更新UI控件的做法是不正确的,会时常出现“线程间操作无效: 从不是创建控件的线程访问它”的异常.处理跨线程更新Winform UI控件常用的方法有4种:1. ...
- 简短总结一下C#里跨线程更新UI(转)
摘自: http://my.oschina.net/sdqxcxh/blog/53707 跨线程更新UI是写多线程程序尤其是通信类的程序经常遇到的问题,这里面主要的问题是冲突,比如数据线程想要更新UI ...
- 简短总结一下C#里跨线程更新UI
摘自: http://my.oschina.net/sdqxcxh/blog/53707 跨线程更新UI是写多线程程序尤其是通信类的程序经常遇到的问题,这里面主要的问题是冲突,比如数据线程想要更新UI ...
- Winform之跨线程更新UI
Winform之跨线程更新UI 使用`Invoke`或者`BeginInvoke`与UI线程交互示例 参考及源码 使用Invoke或者BeginInvoke与UI线程交互示例 private void ...
- C# Winform 跨线程更新UI控件常用方法总结(转)
出处:http://www.tuicool.com/articles/FNzURb 概述 C#Winform编程中,跨线程直接更新UI控件的做法是不正确的,会时常出现“线程间操作无效: 从不是创建控件 ...
- C# 跨线程更新 UI
Winforms 跨线程更新 UI 在 Winforms 中, 所有的控件都包含 InvokeRequired 属性, 如果我们要更新UI,通过它我们可以判断是否需要调用 [Begin]Invoke. ...
- C# WinForms跨线程更新 UI
与在Android中一样, 子线程中更新UI被认为是线程不安全的, 会抛出异常. 子线程返回UI线程中更新UI的一个方法为: 1, 捕获应用的UI线程的上下文; 2, 定义线程任务; 3, 定义线程任 ...
- C#利用委托跨线程更新UI数据
转:http://www.2cto.com/kf/201206/136587.html 在使用C#的过程中,难免会用到多线程,而用多线程之后,线程如何与界面交互则是一个非常头疼的问题.其实不仅仅是界面 ...
随机推荐
- 编写who命令:文件操作,缓冲区与联机帮助
最近阅读UULP(Understanding Unix/Linux Programming),按照书中介绍对Unix/Linux系统编程进行学习梳理,总结如下. 1. who命令能做什么 who命令用 ...
- seleniu IDE 点点滴滴
在使用selenium webdriver +python 的过程中遇见了许多的问题,这些问题在网上都没有找到很好的答案,后来在看selenium IDE的时候发现这里面有很好的解决方法,写写.记记. ...
- .net中的多线程
一.多线程的概念 什么是进程呢?当一个程序开始运行时,它就是一个进程,进程所指包括运行中的程序和程序所使用到的内存和系统资源.而一个进程又是由多个线程所组成的,线程是程序中的一个执行流, ...
- UISegmentedControl 分段器加载不同的viewcontroller
#import <UIKit/UIKit.h> @interface MJSegmentViewController : UIViewController /** * @brief 设置切 ...
- angularJs中筛选功能-angular.filter-1
技术分享:http://www.ncloud.hk/%E6%8A%80%E6%9C%AF%E5%88%86%E4%BA%AB/angular-filter-learn-1/ 以下介绍为自己在使用ang ...
- Windows重新建立图标缓存
有的时候,快捷方式的图标会因各种优化软件而变得面目全非,这时就需要重新建立图标缓存 新建一个文本文档,把文件的后缀名修改成.bat 的例如 icon.bat 在里面填写下面的内容: rem 关闭exp ...
- DWZ (JUI) 教程 dwz框架 刷新dialog解决方案
在DWZ中进行ajax表单提交后,通过回调函数来返回状态结果,以及返回是否需要刷新父页的navTabId. DWZ给我们提供了两个回调函数,一个是子窗口为navTab的navTabAjax ...
- 日志备份和差异备份还原中的常见问题示例(转自&邹建)
--创建测试 CREATE DATABASE db GO --正常备份 BACKUP DATABASE db TO DISK='c:\1.bak' WITH FORMAT BACKUP LOG ...
- SQL Server高级内容之子查询和表链接
1.子查询概念 (1)就是在查询的where子句中的判断依据是另一个查询的结果,如此就构成了一个外部的查询和一个内部的查询,这个内部的查询就是自查询. (2)自查询的分类 1)独立子查询 ->独 ...
- C#DateTime的用法
本文较详细地介绍了C#的DateTime对象的使用方法.DateTime.Now.ToShortTimeString() DateTime dt = DateTime.Now; dt.ToString ...