一、子线程修改主线程**
在主线程中开了一个子线程,如果要在子线程中修改主线程某个控件,会触发异常:“线程间操作无效: 从不是创建控件“button1”的线程访问它。”。
1.正确的写法是需要使用Invoke,Invoke方法需要创建一个委托。如下所示,我要修改一个Button控件的文字:
Thread testThread1=new Thread(new ThreadStart(process1));//主函数中创建一个子线程
testThread1.IsBackground = true;
testThread1.Start();
void process1()
{//使用委托
this.Invoke(new EventHandler(delegate
{
button1.Text = "测试";
}));
}
2.使用Lamda表达式,在.Net Framework3.5及以后的版本中使用Action封装方法,代码如下:
void process1()
{
this.Invoke(new Action(()=>
{
button1.Text = "测试";
}));
}
3.一劳永逸的方法,在 InitializeComponent();下面加上下面这个语句,你就不需要使用上述介绍到的方法了,当是这样写会有什么后果,暂时还不清楚:
System.Windows.Forms.Control.CheckForIllegalCrossThreadCalls = false;//取消线程间的安全检查 解决线程间操作UI问题
一、Invoke和BeginInvoke的区别
上面介绍了Invoke的使用方法,接下来看看Invoke和BeginInvoke的区别到底怎么样???
(1)Invoke() 调用时,Invoke会阻止当前主线程的运行,等到 Invoke() 方法返回才继续执行后面的代码,表现出“同步”的概念。
(2)BeginInvoke() 调用时,当前线程会启用线程池中的某个线程来执行此方法,BeginInvoke不会阻止当前主线程的运行,而是等当前主线程做完事情之后再执行BeginInvoke中的代码内容,表现出“异步”的概念。
private void confirmButton1_Click(object sender, EventArgs e)
{
this.textBox1.Text = "2";
this.Invoke(new EventHandler(delegate
{
this.textBox1.Text += "3";
}));
this.textBox1.Text += "4";
}
//得出的答案是234
private void confirmButton2_Click(object sender, EventArgs e)
{
this.textBox1.Text = "2";
this.BeginInvoke(new EventHandler(delegate
{
this.textBox1.Text += "3";
}));
this.textBox1.Text += "4";
}
//得出的答案是243