c# - org - Criar eventos de un hilo de forma segura
mapwindows 5 (2)
Derivaste tu clase de Control. Un poco inusual, pero si el control está realmente alojado en un formulario, puede usar Me.Invoke () para ordenar la llamada. Por ejemplo:
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
Si este objeto de la clase no está realmente alojado en un formulario, deberá pasar una referencia al formulario para que pueda llamar a Invoke ():
Private mHost As Form
Public Sub New(ByVal host As Form)
mHost = host
End Sub
y use mHost.Invoke (). O BeginInvoke ().
El último truco en el libro es usar su formulario de inicio principal como el objeto de sincronización. Eso no es completamente seguro, pero funciona en el 99% del caso:
Dim main As Form = Application.OpenForms(0)
main.Invoke(New SomethingHappenedDelegate(AddressOf SomethingHappenedThreadSafe), i)
Tenga en cuenta que hay un error en WF que impide que OpenForms () rastree con precisión los formularios abiertos cuando se vuelven a crear dinámicamente.
Tengo algunos problemas con los eventos que surgen del hilo que no es UI, en el sentido de que no deseo tener que manejar el mensaje If me.invoke requerido en cada controlador de eventos agregado al hilo en Form1.
Estoy seguro de que he leído en algún lugar cómo usar un evento de delegado (en SO) pero no puedo encontrarlo.
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
Si desea simplificar todo esto, hay una clase disponible llamada BackgroundWorker que maneja el guiado de hilos de la GUI por usted.