时间:2021-05-20
本文实例简述了C#实现窗体与子线程间通讯的方法,对于C#初学者有一定的借鉴价值。具体方法如下:
一般来说窗体上的UI在默认情况下不允许使用子线程(或者其它非创建控件的UI线程)去控制(这在NET2.0以下是允许的,但是考虑到安全性等问题,从2.0开始就禁止使用这个功能,除非Form的CheckForIllegalCrossThreadCalls=true,不推荐这样使用)。
那么如何实现C#窗体与子线程的交互呢?具体方法如下:
一、使用Invoke或者BeginInvoke方法:
用一个线程,里边调用Invoke或者BeginInvoke方法即可:
public partial class Form1 : Form{public void Processing(int num){int answer = 2;Task t = new Task(() =>{for (int i = 3; i <= num; i++){answer *= i;}this.BeginInvoke(new MethodInvoker(() => { Thread.Sleep(3000); MessageBox.Show("Finished!") }));MessageBox.Show("OK");});t.Start();}public Form1(){InitializeComponent();}private void button1_Click(object sender, EventArgs e){MessageBox.Show("First!");Processing(10);}}这里值得注意:
1)BeginInvoke:这里的“异步”并不是针对UI线程,而是说当Control的BeginInvoke在某个子线程中调用时,子线程中BeginInvoke后面的代码(弹出“Finished”框框)会先执行,然后等到BeginInvoke中的那个委托方法完全执行完毕之后Label才会被赋值。如果改成Invoke,那么“OK”永远在Invoke的委托代码彻底执行完毕之后才被执行。
所以BeginInvoke=Invoke(在UI主线程中,所以不建议在主线程中直接这样调用)
二、线程同步SynchronizedContext:
public partial class Form1 : Form{public void Processing(int num,SynchronizationContext context){int answer = 2;Task t = new Task(() =>{for (int i = 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();}public Form1(){InitializeComponent();}private void button1_Click(object sender, EventArgs e){MessageBox.Show("First!");Processing(10,SynchronizationContext.Current);}}和BeginInvoke、Invoke类似,需要注意:
1)SynchronizationContext:唯独在UI窗体线程中会自动初始化(button1_Click事件中SynchronizationContext.Current为当前窗体),其它线程与线程要交互,必须通过new SynchronizationContext()实现)。
2)Post方法等同于BeginInvoke作用,Send等同于Invoke作用。
大家如果仔细实验代码,还会发现无论何种情况,弹出“Finished”框框总是界面“假死”3秒,是的,证明了以上4个方法都是在UI线程上执行的(只不过是同步或者异步向窗体消息泵发送信息而已)。所以应该“一次性地把数据在子线程中先全部处理干净(在Invoke,BeginInvoke,Send或者Post前得出结果,写代码),然后一次性发送通知给窗体,更新界面即可)。
此外还需要注意:
任何委托(Delegate)也有BeginInvoke方法,它是真正的异步,一旦Invoke一定是开辟一个线程去执行的。
声明:本页内容来源网络,仅供用户参考;我单位不保证亦不表示资料全面及准确无误,也不保证亦不表示这些资料为最新信息,如因任何原因,本网内容或者用户因倚赖本网内容造成任何损失或损害,我单位将不会负任何法律责任。如涉及版权问题,请提交至online#300.cn邮箱联系删除。
本文实例讲述了C#实现winform用子窗体刷新父窗体及子窗体改变父窗体控件值的方法。分享给大家供大家参考。具体如下:第一种方法:用委托,Form2和Form3
本文实例总结了C#子窗体与父窗体通信方法。分享给大家供大家参考。具体如下:【第一种方法:】第一步:创建接口IForm,父窗体继承这个接口publicinterf
本文所述为C#查找素数的程序代码,包括了可视化窗体的代码,找素数的方法可以借鉴。虽然实现的功能简单,不过为了演示一些C#技巧,本文实例中还用到了线程技术、Lis
本文实例讲述了C#实现简单的Login窗口。分享给大家供大家参考。具体实现方法如下:C#制作登录窗体,登录成功之后正确的做法是关闭(close)登录窗体,而不是
本文实例讲述了C#中父窗口和子窗口之间控件互操作的方法。分享给大家供大家参考。具体分析如下:很多人都苦恼于如何在子窗体中操作主窗体上的控件,或者在主窗体中操作子