多线程问题
Multi-threading Issue
我试图在线程中做一个简单的例子
此错误消息
谁能帮我解决一下?
跨线程操作无效:控件 '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
使用Control.CheckForIllegalCrossThreadCalls属性
当控件的创建线程以外的线程试图访问该控件的方法或属性之一时,通常会导致不可预知的结果。常见的无效线程 activity 是对访问控件句柄 属性.
的错误线程的调用
将 CheckForIllegalCrossThreadCalls 设置为 true 以在调试时更轻松地查找和诊断此线程activity。
猜测 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
您需要确保以线程安全的方式访问控件。当您 运行 应用程序时,它使用单个默认线程来创建控件和进行处理。您的组合框控件是使用此默认线程创建的。当您尝试使用新线程向组合框添加项目时,这违反了线程安全规则,因为您只能从创建组合框的线程更改组合框。为此,您需要查看 InvokeRequired 属性 的值以检查您是否需要从不同的线程访问。如果需要调用(如本例所示),则调用 Invoke 方法并传递一个委托对象。委托被指向同一个子例程,但这次它将 运行 它作为默认线程并且不会再发生 "Cross-thread operation not valid" 错误。您可以在这里阅读更多相关信息: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
我试图在线程中做一个简单的例子
此错误消息
谁能帮我解决一下?
跨线程操作无效:控件 '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
使用Control.CheckForIllegalCrossThreadCalls属性
当控件的创建线程以外的线程试图访问该控件的方法或属性之一时,通常会导致不可预知的结果。常见的无效线程 activity 是对访问控件句柄 属性.
的错误线程的调用将 CheckForIllegalCrossThreadCalls 设置为 true 以在调试时更轻松地查找和诊断此线程activity。
猜测 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
您需要确保以线程安全的方式访问控件。当您 运行 应用程序时,它使用单个默认线程来创建控件和进行处理。您的组合框控件是使用此默认线程创建的。当您尝试使用新线程向组合框添加项目时,这违反了线程安全规则,因为您只能从创建组合框的线程更改组合框。为此,您需要查看 InvokeRequired 属性 的值以检查您是否需要从不同的线程访问。如果需要调用(如本例所示),则调用 Invoke 方法并传递一个委托对象。委托被指向同一个子例程,但这次它将 运行 它作为默认线程并且不会再发生 "Cross-thread operation not valid" 错误。您可以在这里阅读更多相关信息: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