如何解决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
就写这么多,欢迎以评论的形式讨论。
朱二(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
就写这么多,欢迎以评论的形式讨论。
相关文章推荐
- C#中跨线程访问控件问题解决方案
- 黑马程序员-解决系统报错“线程间操作无效: 从不是创建控件" txtbox1" 的线程访问它”问题的方法
- 线程间操作无效: 从不是创建控件“...”的线程访问它 问题解决
- C#中跨线程访问控件问题解决方案
- C#中跨线程访问控件问题解决方案
- 如何解决“线程间操作无效: 从不是创建控件的线程访问它”
- VS2005中,C#中跨线程访问控件问题解决方案
- 线程间操作无效: 从不是创建控件“...”的线程访问它 问题解决
- 教你如何解决“线程间操作无效: 从不是创建控件的线程访问它”
- c# CheckForIllegalCrossThreadCalls 解决后台线程访问UI界面控件的问题
- 教你如何解决“线程间操作无效: 从不是创建控件的线程访问它”
- 线程间操作无效: 从不是创建控件“”的线程访问它~~~的解决方法~ 线程间操作无效: 从不是创建控件“Control Name'”的线程访问它问题的解决方案及原理分析
- 教你如何解决“线程间操作无效: 从不是创建控件的线程访问它”
- 转:C#中跨线程访问控件问题解决方案
- C#中跨线程访问控件问题解决方案
- C#中跨线程访问控件问题解决方案
- WinForm解决多线程操作控件问题 线程间操作无效: 从不是创建控件的线程访问它"
- 转:C#中跨线程访问控件问题解决方案
- c# InvokeRequired 解决跨线程访问UI控件的问题
- C#中跨线程访问控件问题解决方案