我试图在线程中做一个简单的例子 这个错误消息 有人可以帮我解决吗?
跨线程操作无效:控制' cmb1'从创建它的线程以外的线程访问。
Imports System.Threading
Public Class Form1
Inherits System.Windows.Forms.Form
Dim th1 As Thread
Dim th2 As Thread
Private Sub Form1_Load (ByVal sender As System.Object, _
ByVal e As System.EventArgs) Handles MyBase.Load
th1 = New Thread(AddressOf proc1)
th2 = New Thread(AddressOf proc2)
th1.Start()
th2.Start()
End Sub
Sub proc1()
Dim iCount As Integer
For iCount = 1 To 10
cmb1.Items.Add(iCount)
Next
End Sub
Sub proc2()
Dim iCount As Integer
For iCount = 11 To 20
cmb2.Items.Add(iCount)
Next
End Sub
End Class
答案 0 :(得分:2)
您需要确保以线程安全的方式访问控件。当您运行应用程序时,它使用单个默认线程来创建控件并进行处理。您正在使用此默认线程创建组合框控件。当您尝试使用新线程将项目添加到组合框时,它违反了线程安全规则,因为您只能从创建它们的线程更改组合框。为此,您需要查看InvokeRequired属性的值,以检查是否需要从其他线程进行访问。如果需要调用(在这种情况下),则调用Invoke方法并传递委托对象。委托被指向相同的子例程,但这次它将作为默认线程运行,并且不再发生“跨线程操作无效”错误。您可以在此处详细了解:http://msdn.microsoft.com/en-us/library/ms171728%28v=vs.85%29.aspx
此外,以下是您应该如何重新编写代码以合并代理调用:
Imports System.Threading
Public Class Form1
Inherits System.Windows.Forms.Form
Dim th1 As Thread
Dim th2 As Thread
' Create the delegates that are needd to make safe thread calls
Private Delegate Sub proc1Delegate()
Private Delegate Sub proc2Delegate()
Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
th1 = New Thread(AddressOf proc1)
th2 = New Thread(AddressOf proc2)
th1.Start()
th2.Start()
End Sub
Sub proc1()
' Check if invoke is required
If Me.InvokeRequired Then
' An invoke is required so we call the delegate and point back to the same subroutine
Me.Invoke(New proc1Delegate(AddressOf proc1))
Else
' Original code goes only gets run on default thread
Dim iCount As Integer
For iCount = 1 To 10
cmb1.Items.Add(iCount)
Next
End If
End Sub
Sub proc2()
' Check if invoke is required
If Me.InvokeRequired Then
' An invoke is required so we call the delegate and point back to the same subroutine
Me.Invoke(New proc2Delegate(AddressOf proc2))
Else
' Original code goes only gets run on default thread
Dim iCount As Integer
For iCount = 11 To 20
cmb2.Items.Add(iCount)
Next
End If
End Sub
End Class
答案 1 :(得分:-1)
使用Control.CheckForIllegalCrossThreadCalls属性
当控件的创建线程以外的线程尝试访问该控件的某个方法或属性时,通常会导致不可预测的结果。一个常见的无效线程活动是在错误的线程上调用访问控件的Handle属性。
将CheckForIllegalCrossThreadCalls设置为true可在调试时更轻松地查找和诊断此线程活动。
答案 2 :(得分:-1)
猜测cmb1是一个列表框或者什么......你不能操纵不同线程中的物理对象。只能编辑变量等抽象对象。
将整数放入列表中,并在线程完成时创建一个变量。
Dim IntList As New List(Of Integer)
Dim ThreadDone As Boolean = False
然后在线程中进行编码。
For iCount = 1 To 10
IntList.Add(iCount)
Next
ThreadDone = True
使用计时器检查线程何时完成。或者,使用BackgroundWorker而不是New Thread
。 BackgroundWorker将执行多线程并在完成后触发RunWorkerCompleted事件。
Private Sub Timer1_Tick()
If ThreadDone = True
cmb1.AddRange(IntList)
End If
End Sub