C# 从线程安全地引发事件
对于从非UI线程引发的事件,我遇到了一些问题,因为我不希望必须在Form1中添加到线程的每个事件处理程序上处理If me.invokererequired 我确信我在某个地方读过如何使用委托事件(如此),但我找不到它C# 从线程安全地引发事件,c#,vb.net,multithreading,C#,Vb.net,Multithreading,对于从非UI线程引发的事件,我遇到了一些问题,因为我不希望必须在Form1中添加到线程的每个事件处理程序上处理If me.invokererequired 我确信我在某个地方读过如何使用委托事件(如此),但我找不到它 Public Class Form1 Private WithEvents _to As New ThreadedOperation Private Sub Button_Click(ByVal sender As System.Object, ByVal e
Public Class Form1
Private WithEvents _to As New ThreadedOperation
Private Sub Button_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button.Click
_to.start()
End Sub
Private Sub _to_SomthingHappend(ByVal result As Integer) Handles _to.SomthingHappend
TextBox.Text = result.ToString //cross thread exception here
End Sub
End Class
Public Class ThreadedOperation
Public Event SomthingHappend(ByVal result As Integer)
Private _thread As Threading.Thread
Public Sub start()
If _thread Is Nothing Then
_thread = New Threading.Thread(AddressOf Work)
End If
_thread.Start()
End Sub
Private Sub Work()
For i As Integer = 0 To 10
RaiseEvent SomthingHappend(i)
Threading.Thread.Sleep(500)
Next
End Sub
End Class
您从控件派生了类。有点不寻常,但如果控件实际上托管在表单上,则可以使用Me.Invoke()封送调用。例如:
Private Delegate Sub SomethingHappenedDelegate(ByVal result As Integer)
Private Sub Work()
For i As Integer = 0 To 10
Me.Invoke(New SomethingHappenedDelegate(AddressOf SomethingHappenedThreadSafe), i)
Threading.Thread.Sleep(500)
Next
End Sub
Private Sub SomethingHappenedThreadSafe(ByVal result As Integer)
RaiseEvent SomthingHappend(result)
End Sub
如果该类对象实际上未托管在表单上,则需要传递对该表单的引用,以便它可以调用Invoke():
并使用mHost.Invoke()。或开始唤醒()
本书的最后一个技巧是使用主启动窗体作为同步对象。这并不完全安全,但在99%的情况下都有效:
Dim main As Form = Application.OpenForms(0)
main.Invoke(New SomethingHappenedDelegate(AddressOf SomethingHappenedThreadSafe), i)
请注意,WF中存在一个bug,它阻止OpenForms()在动态重新创建打开的表单时准确跟踪它们。如果您想简化所有这些,可以使用一个名为BackgroundWorker的类来处理GUI线程封送。是的,我非常了解/使用后台工作程序,但是,这个组件需要对其线程有更大的控制。我接受了第二个建议,即传递主机控件(我传递的是控件对象,而不是窗体)。谢谢
Dim main As Form = Application.OpenForms(0)
main.Invoke(New SomethingHappenedDelegate(AddressOf SomethingHappenedThreadSafe), i)