线程间操作无效: 从不是创建控件“...”的线程访问它。
来源:互联网 发布:php des加密解密 编辑:程序博客网 时间:2024/05/16 02:42
访问 Windows 窗体控件本质上不是线程安全的。如果有两个或多个线程操作某一控件的状态,则可能会迫使该控件进入一种不一致的状态。还可能出现其他与线程相关的 bug,包括争用情况和死锁。确保以线程安全方式访问控件非常重要。
.NET Framework 有助于在以非线程安全方式访问控件时检测到这一问题。在调试器中运行应用程序时,如果创建某控件的线程之外的其他线程试图调用该控件,则调试器会引发一个 InvalidOperationException,并提示消息:“从不是创建控件 control name 的线程访问它。”
此异常在调试期间和运行时的某些情况下可靠地发生。强烈建议您在显示此错误信息时修复此问题。在调试以 .NET Framework 2.0 版之前的 .NET Framework 编写的应用程序时,可能会出现此异常。
注意
可以通过将 CheckForIllegalCrossThreadCalls 属性的值设置为 false 来禁用此异常。这会使控件以与在 Visual Studio 2003 下相同的方式运行。
对于这个问题的处理,如下所示:
例子的界面如下
注意这里用到的这个backgroundworker控件。
下面的代码很直观的解释了解决此问题的方法:
namespace WindowsFormsApplication1
{
public partial class Form1 : Form
{
public delegate void setTextCallBack(string text);
private Thread demoThread = null;
public Form1()
{
InitializeComponent();
}
#region 非线程安全方式
// 此事件句柄创建一个线程以非安全方式调用一个windows窗体控件,此处会报标题中提到的错误
private void setTextUnsafeBtn_Click(object sender, EventArgs e)
{
this.demoThread = new Thread(new ThreadStart(this.ThreadProcUnsafe));
this.demoThread.Start();
}
//此方法在工作者线程执行并且对TextBox控件作非安全调用
private void ThreadProcUnsafe()
{
this.textBox1.Text = "This text was set unsafely.";
}
#endregion
#region 线程安全方式
// 此事件句柄创建一个以线程安全方式调用windows窗体控件的线程
private void setTextSafeBtn_Click(object sender, EventArgs e)
{
this.demoThread = new Thread(new ThreadStart(this.ThreadProcSafe));
this.demoThread.Start();
}
// 此方法在工作者线程执行并且对TextBox控件作线程安全调用
private void ThreadProcSafe()
{
this.SetText("This text was set safely.");
}
// 如果调用线程和创建TextBox控件的线程不同,这个方法创建
// 代理SetTextCallback并且自己通过Invoke方法异步调用它
// 如果相同则直接设置Text属性
private void SetText(string text)
{
if (this.textBox1.InvokeRequired)
{
setTextCallBack d = new setTextCallBack(SetText);
this.Invoke(d, new object[] { text });
}
else
{
this.textBox1.Text = text;
}
}
#endregion
#region BackgroudWorker方式
// BackgroundWorker是执行异步操作的首选方式
// 此事件句柄通过调用RunWorkerAsync开启窗体的BackgroundWorker
// 当BackgroundWorker引发RunworkerCompleted事件的时候TextBox
// 控件的Text属性被设置
private void setTextBackgroundWorkerBtn_Click(object sender, EventArgs e)
{
this.backgroundWorker1.RunWorkerAsync();
}
private void backgroundWorker1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
this.textBox1.Text = "This text was set safely by BackgroundWorker.";
}
#endregion
}
}
参考了微软资料和网络。
无意中在网上遇到了总结更好的一篇文章,奇文共赏,感谢作者:
来自菩提树下的杨过http://www.cnblogs.com/yjmyzz/archive/2009/11/25/1610253.html
- WinForm中线程问题:线程间操作无效: 从不是创建控件“...”的线程访问它
- c#线程问题:线程间操作无效:从不是创建控件 的线程访问它
- WinForm中线程问题:线程间操作无效: 从不是创建控件“...”的线程访问它
- “线程间操作无效:从不是创建控件“XX”的线程访问它”的解决方法
- 线程间操作无效: 从不是创建控件“”的线程访问它的解决方法
- 小结“线程间操作无效: 从不是创建控件的线程访问它” 错误的解决方法
- 小结“线程间操作无效: 从不是创建控件的线程访问它” 错误的解决方法
- 线程间操作无效: 从不是创建控件“”的线程访问它~~~的解决方法!
- 线程间操作无效: 从不是创建控件“”的线程访问它~~~的解决方法~
- 小结“线程间操作无效: 从不是创建控件的线程访问它” 错误的解决方法
- 小结“线程间操作无效: 从不是创建控件的线程访问它” 错误的解决方法
- 线程间操作无效 从不是创建控件“___”的线程访问它”解决方法的疑惑
- 线程间操作无效: 从不是创建控件“”的线程访问它~~~的解决方法
- C# 线程间操作无效: 从不是创建控件“”的线程访问它~~~的解决方法~
- 线程间操作无效: 从不是创建控件“”的线程访问它~~~的解决方法~
- 线程间操作无效: 从不是创建控件“”的线程访问它~~~的解决方法
- 线程间操作无效: 从不是创建控件“”的线程访问它~~~的解决方法~
- 线程间操作无效: 从不是创建控件“”的线程访问它~~~的解决方法~
- 【总结】IE和Firefox的Javascript兼容性总结(转)
- 如何安装一个新的语言?
- oracle 数据库服务详解
- Processing Dirty Regions
- 初始化成员列表
- 线程间操作无效: 从不是创建控件“...”的线程访问它。
- 唐山大地震观后感
- 菜鸟要开始学习了
- 如何通过外部csv文件编辑产品的价格?
- poj1077
- 与 static 相关的总结
- 如何使用Magento翻译工具?
- 经典SQL语句大全
- 复制粘贴功能失效的解决办法