2010-10-04 20 views
5

vea el programa a continuación. Comienzo un nuevo hilo x con la función abc, luego hago una tarea más larga. ¿Por qué x solo comienza después del extremo sub? ¿No debería comenzar enseguida, antes de dormir?¿Por qué mi hilo no está comenzando de inmediato?

Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click 
     Dim x As New Threading.Thread(AddressOf abc) 
     x.SetApartmentState(Threading.ApartmentState.MTA) 
     x.Start() 

     System.Threading.Thread.Sleep(5000) 
    End Sub 





Sub abc() 
    For i As Integer = 0 To 10 Step 1 
     Me.lblStatus.Text = "Testing DB connection (timeout in: " + i.ToString() + "s)" 
     'Me.StatusStrip1.Invoke(
     MsgBox(i.ToString) 
     System.Threading.Thread.Sleep(1000) 
    Next 
End Sub 



Editar:
La solución es la siguiente:

(A) Poner tanto los intentos de conexión y la cuenta atrás de tiempo de espera en hilos separados.
(B) Actualización de la interfaz de usuario de la siguiente manera:

If Me.InvokeRequired Then 
     Me.Invoke(pUpdateStatusMessage, "Successfully connected.") 
    Else 
     UpdateStatusMessage("Successfully connected.") 
    End If 

Con esta declarada a nivel mundial, por lo que ningún argumento para aprobar es necesario:

Delegate Sub t_pUpdateStatusText(ByVal strMessage As String) 
Public pUpdateStatusMessage As t_pUpdateStatusText = New t_pUpdateStatusText(AddressOf UpdateStatusMessage) 

Public Sub UpdateStatusMessage(ByVal strMessage As String) 
    Me.lblStatus.Text = strMessage 
    Me.StatusStrip1.Update() 
End Sub 
+0

¿Cómo se verifica que el hilo solo se inicia una vez que finaliza el método? ¿Estás mirando la etiqueta, o estás esperando que se dispare un punto de interrupción? –

+0

En realidad, cuando no se muestra, configuro un punto de interrupción. –

Respuesta

10

La función abc se iniciará antes de que finalice el método Button1_Click. ¿Qué está causando la confusión es 2 cosas

La primera es que está actualizando directamente la interfaz de usuario de un hilo de fondo con la siguiente línea

Me.lblStatus.Text = "Testing DB connection (timeout in: " + i.ToString() + "s)" 

Este código es incorrecto y puede causar problemas más adelante. Debe usar la llamada Invoke para cambiar realmente la IU. Como lo haces en la segunda línea que nos lleva al siguiente problema.

La llamada Invoke es síncrona. Se ejecuta esencialmente empujando un mensaje en la cola de mensajes de Windows y esperando a que se procese antes de volver. La llamada Thread.Sleep que agregó en el hilo principal impide que la cola de mensajes se ejecute realmente. Esto efectivamente detiene el hilo de fondo hasta que la llamada Sleep finalice dando la apariencia de que el hilo de fondo no se está ejecutando.

2

va a actualizar la interfaz de usuario de un no Hilo de interfaz de usuario. Esto no está permitido y puede llevar a un comportamiento extraño. No sé si eso es lo que está causando su comportamiento de demora, pero primero tendrá que resolverlo.

0

Para agregar a lo que otros dicen, puede crear un delegado para definir la firma de sus requisitos de actualización de control (en este caso, estoy asumiendo textbox y string, pero eso se puede definir como lo necesite), y luego crea un método que sigue a esa firma de delegado que se invoca recurrentemente de manera asíncrona si es necesario.

Algo como esto:

private delegate void ControlUpdateTextHandler(TextBox ctrl, string text); 
public void UpdateControlText(TextBox ctrl, string text) 
{ 
    if (ctrl.InvokeRequired) 
    { 
     ctrl.BeginInvoke((ControlUpdateTextHandler)UpdateControlText, ctrl, text); 
    } 
    else 
     ctrl.Text = text; 
} 

debería funcionar si se llama desde el hilo "correcta" (porque InvokeRequired será falsa si esto es llamado por el subproceso que posee el control) simplemente actualizando el texto, o desde el subproceso "incorrecto" (porque InvokeRequired será verdadero si se llama desde un subproceso diferente), al poner en cola la invocación que realizará el subproceso de UI.

0

Quizás no esté relacionado con su pregunta, pero para actualizar la interfaz de usuario de un hilo separado, le sugiero que use el BackgroundWorker. coloque la función abc() en DoWork y use ProgessChanged para actualizar la IU.

Cuestiones relacionadas