C#实现窗体与子线程的交互的方法

2020-01-06 12:54:47于丽
易采站长站为您分析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类似,需要注意: