C#实现窗体与子线程的交互的方法
本文实例简述了C#实现窗体与子线程间通讯的方法,对于C#初学者有一定的借鉴价值。具体方法如下:
一般来说窗体上的UI在默认情况下不允许使用子线程(或者其它非创建控件的UI线程)去控制(这在NET2.0以下是允许的,但是考虑到安全性等问题,从2.0开始就禁止使用这个功能,除非Form的CheckForIllegalCrossThreadCalls=true,不推荐这样使用)。
那么如何实现C#窗体与子线程的交互呢?具体方法如下:
一、使用Invoke或者BeginInvoke方法:
用一个线程,里边调用Invoke或者BeginInvoke方法即可:
publicpartialclassForm1:Form { publicvoidProcessing(intnum) { intanswer=2; Taskt=newTask(()=> { for(inti=3;i<=num;i++) { answer*=i; } this.BeginInvoke(newMethodInvoker(()=>{Thread.Sleep(3000);MessageBox.Show("Finished!")})); MessageBox.Show("OK"); }); t.Start(); } publicForm1() { InitializeComponent(); } privatevoidbutton1_Click(objectsender,EventArgse) { MessageBox.Show("First!"); Processing(10); } }
这里值得注意:
1)BeginInvoke:这里的“异步”并不是针对UI线程,而是说当Control的BeginInvoke在某个子线程中调用时,子线程中BeginInvoke后面的代码(弹出“Finished”框框)会先执行,然后等到BeginInvoke中的那个委托方法完全执行完毕之后Label才会被赋值。如果改成Invoke,那么“OK”永远在Invoke的委托代码彻底执行完毕之后才被执行。
所以BeginInvoke=Invoke(在UI主线程中,所以不建议在主线程中直接这样调用)
二、线程同步SynchronizedContext:
publicpartialclassForm1:Form { publicvoidProcessing(intnum,SynchronizationContextcontext) { intanswer=2; Taskt=newTask(()=> { for(inti=3;i<=num;i++) { answer*=i; } SynchronizationContext.SetSynchronizationContext(context); SynchronizationContext.Current.Post((obj)=>{Thread.Sleep(3000);MessageBox.Show("Finished");},null); MessageBox.Show("Last"); }); t.Start(); } publicForm1() { InitializeComponent(); } privatevoidbutton1_Click(objectsender,EventArgse) { MessageBox.Show("First!"); Processing(10,SynchronizationContext.Current); } }
和BeginInvoke、Invoke类似,需要注意:
1)SynchronizationContext:唯独在UI窗体线程中会自动初始化(button1_Click事件中SynchronizationContext.Current为当前窗体),其它线程与线程要交互,必须通过newSynchronizationContext()实现)。
2)Post方法等同于BeginInvoke作用,Send等同于Invoke作用。
大家如果仔细实验代码,还会发现无论何种情况,弹出“Finished”框框总是界面“假死”3秒,是的,证明了以上4个方法都是在UI线程上执行的(只不过是同步或者异步向窗体消息泵发送信息而已)。所以应该“一次性地把数据在子线程中先全部处理干净(在Invoke,BeginInvoke,Send或者Post前得出结果,写代码),然后一次性发送通知给窗体,更新界面即可)。
此外还需要注意:
相关文章
- C# 连接SFTP
- C# 税务电子发票接口开发「建议收藏」
- C# 三种方式实现Socket数据接收(经典)
- 磁盘配额的wmi版本(C#)
- asp.net(c#)两种随机数的算法,可用抽考题
- c#datetime方法应用介绍
- C#访问PostGreSQL数据库的方法
- C#WINFORM强制让窗体获得焦点的方法代码
- c#.net动态读取走马灯代码实例分享
- C#调用Java类的实现方法
- 浅谈C#2.0泛型中的变化:default关键字
- C#实现任意数据类型转成json格式输出
- C#波形图控件制作示例程序
- C#正则表达式分解和转换IP地址实例(C#正则表达式大全c#正则表达式语法)
- .net/c#memcached缓存获取所有缓存键的方法步骤
- c#入门之循环语句使用详解(for循环、do/while)
- C#实现提高xml读写速度的方法
- C#实现线程安全的简易日志记录方法
- C#实现在两个数字之间生成随机数的方法
- C#中抽象方法与虚拟方法的区别
- C#实现图片上传与浏览切换的方法
- C#中事件的动态调用实现方法
- C#逐行读取txt文件的方法