线程间操作无效: 从不是创建控件的线程访问它。

作者: harde 分类: DotNet 发布时间: 2010-03-19 17:41

其实很早就想写这么篇文章了,只不过一直很懒再者觉得自己对线程的理解还不够深刻
写出来怕真正的高手笑话。
今天朋友遇到了这个问题,考虑下,还是写出来吧。
错误详细信息应该为:
线程间操作无效: 从不是创建控件“XXX”的线程访问它。

问题看起来其实很简单,解决起来其实也很简单…
就我知道的有三种方法。
在说解决方案前,先了解点相关信息。

引用MSDN上而定话:访问 Windows 窗体控件本质上不是线程安全的。如果有两个或多个线程操作某一控件的状态,则可能会迫使该控件进入一种不一致的状态。还可能出现其他与线程相关的 bug,包括争用情况和死锁。确保以线程安全方式访问控件非常重要。

而我们出现这个错误时,应该都在做这个操作…

看个简单例子
在窗体加载时需要载入大量数据
我们就会想到,由新的线程来加载数据,主线程继续加载窗体
这样用户不会感觉“卡”了。
但问题是,当数据加载完成,需要赋值到原窗体控件时
就会报错…

貌似说这些没什么意义哈…
看下解决办法
1、把CheckForIllegalCrossThreadCalls设置为false
但是同样,这样做也就容易造成其他线程的问题和死锁
所以这个是个最简单但又最不好的解决方案

2、利用委托
举个例子
txt_a 是一个TextBox
我们现在要在县城中修改他的Text值

delegate void SetTextCallBack(string text);
private void SetText(string text)
{
if (this.txt_a.InvokeRequired)
{
SetTextCallBack stcb = new SetTextCallBack(SetText);
this.Invoke(stcb , new object[] { text});
}
else
{
this.txt_a.Text = text;
}
}

private void LoadData()
{
SetText(“测试”);
}

//窗体加载时,用线程加载数据
private void Frm_ImportManager_Load(object sender, EventArgs e)
{
ThreadStart ts = new ThreadStart(LoadData);
Thread thread = new Thread(ts);
thread.Name = “LoadData”;
thread.Start();
}
[/csharp” collapse=”true” line=”1]
试一下,OK了吧。
这是最佳的方案

3、改回用单线程….别拿板砖拍我,挺好的啊,不就是用户体验差了点么…

大家可以参考下MSDN:
如何:对 Windows 窗体控件进行线程安全调用
http://msdn.microsoft.com/zh-cn/visualc/ms171728(VS.85,printer).aspx

⬆️⬆️⬆️不要钱、不用登录、没有广告⬆️⬆️⬆️


如果文章对您有帮助,请至少点下⬆️⬆️⬆️上面⬆️⬆️⬆️的赞,您的鼓励是对我创作的最大支持。
如果没能帮到您,那么很遗憾,如果方便的话,还请在评论区告诉我为什么,谢谢。

⬇️⬇️⬇️下面这个要钱⬇️⬇️⬇️

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注