C#实现窗体与子线程的交互的方法
本文实例简述了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一定是开辟一个线程去执行的。
上一篇: C#中csv文件与DataTable互相导入处理实例解析
下一篇: 阿里图标库的使用