您的位置:首页 > 其它

如何解决DotNET中跨线程访问控件的问题

2008-10-28 08:51 405 查看
如何解决DotNET中跨线程访问控件的问题

朱二(2008.10,转载请保留作者)

如果您对这篇小文感兴趣的话,或许您在编程中时候碰到过以下类似的异常提示:
1、线程间操作无效: 从不是创建控件“X”的线程访问它。(X是控件名称)
2、"在该控件上执行的操作正从错误的线程调用。使用 Control.Invoke 或 Control.BeginInvoke 封送到正确的线程才能执行此操

作。"

看到这种提示,极有可能是跨线程访问控件造成的。举个小例子,窗体FormA上有一位名叫TextBoxA的TextBox大哥。
代码如下:

Private Sub FormA_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load

Dim th As New System.Threading.Thread(AddressOf CrossThreadCallTest)

th.Start()

End Sub

Public Sub CrossThreadCallTest()

TextBoxA.Text = "ABC"

End Sub

简单解释一下:
窗体加载时创建线程th执行过程CrossThreadCallTest,在线程th里面设置TextBoxA的文本。
TextBoxA是主线程创建的,在th线程里访问,造成跨线程访问Windows控件,通常您会得到类似上面的第一个提示。
错误消息如下:
在该控件上执行的操作正从错误的线程调用。使用 Control.Invoke 或 Control.BeginInvoke 封送到正确的线程才能执行此操作。

这样的问题在使用Visual Studio 2003的时候是遭遇不到的,在.NET Framework 2.0中,要想和避免同样的问题,可以采用一个简

单的方法,只要将TextBox类的CheckForIllegalCrossThreadCalls属性设置为False就可以,新代码如下

Private Sub FormA_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load

TextBox.CheckForIllegalCrossThreadCalls = False

Dim th As New System.Threading.Thread(AddressOf CrossThreadCallTest)

th.Start()

End Sub

但CheckForIllegalCrossThreadCalls并不能解决所有的问题,比如TreeView控件就没有这么幸运,通常会抛出上面第2种提示。并且

对于跨线程访问Windows控件,微软似乎并不推荐使用CheckForIllegalCrossThreadCalls,而推荐采用更为安全的访问技术。
下面这个例子是跨线程向TreeView添加节点的例子:

Private Sub FormA_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load

Dim th As New System.Threading.Thread(AddressOf CrossThreadCallTest)

th.Start()

End Sub

Public Sub CrossThreadCallTest()

Dim delAdd As New AddNodeDelegate(AddressOf AddTreeNode)

TreeView1.BeginInvoke(delAdd)

End Sub

Private Delegate Sub AddNodeDelegate()

Private Sub AddTreeNode()

TreeView1.Nodes.Add("ABC")

End Sub

这样一来,AddTreeNode过程还是在主线程里运行,当然不会出现跨线程的问题了,对代码稍加改动,就能说明:

Private Sub FormA_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load

System.Threading.Thread.CurrentThread.Name = "Main"

Dim th As New System.Threading.Thread(AddressOf CrossThreadCallTest)

th.Name = "th"

th.Start()

End Sub

Public Sub CrossThreadCallTest()

Dim delAdd As New AddNodeDelegate(AddressOf AddTreeNode)

TreeView1.BeginInvoke(delAdd)

End Sub

Private Delegate Sub AddNodeDelegate()

Private Sub AddTreeNode()

TreeView1.Nodes.Add("ABC")

'显示的应该是Main

MessageBox.Show(System.Threading.Thread.CurrentThread.Name)

End Sub

就写这么多,欢迎以评论的形式讨论。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐