黑马程序员技术交流社区
标题:
对 Windows 窗体控件进行跨线程安全调用
[打印本页]
作者:
吴步兵
时间:
2012-11-9 17:54
标题:
对 Windows 窗体控件进行跨线程安全调用
本帖最后由 吴步兵 于 2012-11-16 22:22 编辑
今天看了多线程的教学视频,碰到不允许跨线程调用Windows窗体的错误。教学视频里只是用TextBox.CheckForIllegalCrossThreadCalls = false;过滤掉检查。后来自己查看了MSDN,知道了跨线程调用控件的两种方法。
方法一、查询控件的 InvokeRequired 属性,如果 InvokeRequired 返回 true,则使用实际调用控件的委托来调用 Invoke,如果 InvokeRequired 返回 false,则直接调用控件。实例如下
delegate void SetTextCallback(string text);
//---------------------使用 Invoke 实现的安全访问-----------------
private void setTextSafeBtn_Click(object sender, EventArgs e)
{
Thread demoThread = new Thread(new ThreadStart(ThreadProcSafe));
demoThread.Start();
}
private void ThreadProcSafe()
{
this.SetText("这是使用Invoke实现安全的调用方法.");
}
private void SetText(string text)
{
//检查控件的InvokeRequired是否为true,是则ThreadProcSafe方法会创建SetTextCallback的一个实例,并将该实例传递给窗体的Invoke方法。
//这使得SetText方法被创建TextBox控件的线程调用,而且在此线程上下文中将直接设置Text属性
if (this.textBox1.InvokeRequired)
{
SetTextCallback d = new SetTextCallback(SetText);
this.Invoke(d, new object[] { text });
}
else//InvokeRequired为false则直接赋值
{
this.textBox1.Text = text;
}
}
复制代码
方法二:使用 BackgroundWorker 进行线程安全调用
在应用程序中实现多线程的首选方式是使用BackgroundWorker组件。BackgroundWorker 组件使用事件驱动模型实现多线程。后台线程运行 DoWork 事件处理程序,而创建控件的线程运行 ProgressChanged 和 RunWorkerCompleted 事件处理程序。可以从 ProgressChanged 和 RunWorkerCompleted 事件处理程序调用控件。实例如下:
//-------------------------使用 BackgroundWorker 实现的安全访问(还是不太明白)-----------------------------
private void setTextBackgroundWorkerBtn_Click(object sender, EventArgs e)
{
this.backgroundWorker1.RunWorkerAsync();
}
private void backgroundWorker1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
this.textBox1.Text = "使用 BackgroundWorker 实现的安全访问.";
}
复制代码
但两种方法到底有什么区别和优缺点呢。还是搞不太懂啊。
欢迎光临 黑马程序员技术交流社区 (http://bbs.itheima.com/)
黑马程序员IT技术论坛 X3.2