.net - thread - Control.Invoke está colgando
invoke vb net (2)
Está utilizando Thread.Join
para dejar que el hilo de la interfaz de usuario se detenga hasta que Thread.Join
el otro hilo. Al mismo tiempo, utiliza Control.Invoke
para permitir que el subproceso de la interfaz de usuario realice alguna acción. Esto no funcionará porque el subproceso de la interfaz de usuario está esperando que termine el otro subproceso.
Le sugiero que elimine la llamada de Thread.Join
o realice su acción en el hilo de UI si desea que espere a que termine la acción.
He visto un montón de publicaciones relacionadas con el problema del control. Invoco aplicaciones colgantes, pero en su mayoría parecían estar restringidas a las que se ejecutan en .NET 1.1. También he visto sugerencias para utilizar .BeginInvoke en su lugar, lo he intentado pero fue en vano. .BeginInvoke no se bloquea, pero tampoco llama al delegado. Mi principal preocupación es que he usado. Invoco durante años sin problemas y tengo una gran aplicación en el campo que lo usa ampliamente y me preocupa que este problema surja allí. No estoy haciendo nada diferente, por lo que puedo decir, entre mi código de trabajo y el código que falla. He escrito un bit de código simple que reproduce el problema (todo en 4.0 VS2010):
Public Class Form1
Private WithEvents sat As TestInvoke
Private Delegate Sub doTheUpdateDelegate(ByVal message As String)
Private Sub Button1_Click(sender As System.Object, e As System.EventArgs) Handles Button1.Click
sat = New TestInvoke
sat.startAThread()
End Sub
Public Class TestInvoke
Public Event UpdateControl()
Public Sub startAThread()
Dim t As New Threading.Thread(AddressOf _startAThread)
Dim trace As String
trace = "a"
t.SetApartmentState(Threading.ApartmentState.STA)
t.Start()
t.Join()
End Sub
Protected Sub _startAThread()
Try
For k = 0 To 10
System.Threading.Thread.Sleep(1000)
k += 1
RaiseEvent UpdateControl()
Next
Catch ex As Exception
MsgBox(ex.Message)
End Try
End Sub
End Class
Private Sub sat_UpdateControl() Handles sat.UpdateControl
Try
Call doTheupdate(Now.ToString)
Catch ex As Exception
MsgBox(ex.Message)
End Try
End Sub
Private Sub doTheUpdate(ByVal message As String)
Try
If Button1.InvokeRequired = True Then
Dim objParams As Object() = {message}
''hangs on the following line
Button1.Invoke(New doTheUpdateDelegate(AddressOf doTheUpdate), objParams)
Else
Button1.Text = message
End If
Catch ex As Exception
MsgBox(ex.Message)
End Try
End Sub
End Class
Si alguien puede ver lo que he hecho mal aquí, ¡realmente lo agradecería!
Solo hay una razón por la que se cuelgue una llamada Control.Invoke (). O una llamada BeginInvoke () no ejecuta su objetivo, lo mismo. Sucede cuando el hilo principal del programa, el hilo de UI, no está inactivo y ocupado haciendo otra cosa.
Lo que la "otra cosa" podría ser está en todo el mapa. Lo peor que podría hacer es que el hilo principal espere a que se complete el hilo del trabajador. Es un punto muerto garantizado si usa Invoke ().
La condición es muy fácil de diagnosticar, use Debug + Break All y Debug + Windows + Threads. Haga doble clic en el hilo principal y observe la ventana Pila de llamadas. La parte superior de la traza de la pila debe decir "Transición gestionada a nativa", la siguiente debajo debe ser FPushMessageLoop (). Si ves algo más, entonces has encontrado el código que causa el punto muerto.