2008-10-15 10 views

Respuesta

10

Hay una regla general que dice que no actualice la UI de ningún hilo que no sea el propio de la interfaz de usuario. Usar las características de BackgroundWorker es una buena idea, pero no desea hacerlo y algo sucede en un hilo diferente, debe hacer una "Invoke" o BeginInvoke para forzar al delegado a ejecutar el método en el hilo de la interfaz de usuario.

Edición: Jon B hizo este buen punto en los comentarios:

Tenga en cuenta que Invoke() es sincrónica y BeginInvoke() es asíncrona. Si usa Invoke(), debe tener cuidado de no causar un punto muerto . Recomendaría BeginInvoke() a menos que realmente necesite la llamada para que sea sincrónica.

Algunos sencillo código de ejemplo:

// Updates the textbox text. 
private void UpdateText(string text) 
{ 
    // Set the textbox text. 
    m_TextBox.Text = text; 
} 

public delegate void UpdateTextCallback(string text); 

// Then from your thread you can call this... 
m_TextBox.Invoke(new UpdateTextCallback(this.UpdateText), 
    new object[]{"Text generated on non-UI thread."}); 

El código anterior es de un FAQ sobre él here y una más larga más involucrado uno here.

+0

¿Qué hace exactamente el m_TextBox.Invoke? ¿Obliga al delegado a ejecutarse en el hilo de la interfaz de usuario? – Yttrium

+4

Exactamente. Tenga en cuenta que Invoke() es sincrónico y BeginInvoke() es asincrónico. Si usa Invoke(), debe tener cuidado de no provocar un punto muerto. Recomendaría BeginInvoke() a menos que realmente necesite que la llamada sea sincrónica. –

+0

Buena llamada, Jon B. Debería haber mencionado eso. Voy a editar para reflejar el punto. –

5

¿Por qué no quieres hacerlo con BackgroundWorker? Tiene un fantástico evento de devolución de llamada llamado ProgressChanged que permite que el hilo de la interfaz de usuario conozca las actualizaciones, perfecto para actualizaciones de tipo de barra de progreso y similares.

link to details

1

Hay una discusión relacionada con este here y uno here.

Básicamente, utiliza Invoke para lograrlo.

¡La mejor de las suertes!

1

También consideraría InvokeRequired (VS2008 solamente) al llamar a Invoke. Hay momentos en que no actualizará la UI desde un hilo separado. Se ahorra la sobrecarga de crear el delegado, etc.

if (InvokeRequired) 
     { 
      //This.Invoke added to circumvent cross threading exceptions. 
      this.Invoke(new UpdateProgressBarHandler(UpdateProgressBar), new object[] { progressPercentage }); 
     } 
     else 
     { 
      UpdateProgressBar(progressPercentage); 
     } 
Cuestiones relacionadas