2009-12-15 12 views
16

Saludos, Estoy desarrollando alguna aplicación en C#. En este momento estoy tratando con el enhebrado y tengo una pregunta que tengo en mente. ¿Cuál es la diferencia entre Invoke y BeginInvoke? leí un poco de hilo y me encontré con algo de información útil aquí: hereInvocar y BeginInvoke

Sin embargo ¿cuál es la diferencia entre la invocación y BeginInvoke en el siguiente código:

private void ProcessRoutine() 
{ 
    for (int nValue = StartFrom; nValue <= EndTo; nValue++) 
    { 
     this.Invoke(this.MyDelegate, nValue); 
     //this.BeginInvoke(this.MyDelegate, nValue); 
    } 
    MessageBox.Show("Counting complete!"); 
} 
private void MessageHandler(int progress) 
{ 
    lblStatus.Text = lblStatus.Text = "Processing item: " + progress.ToString(); 
    progressBar1.Value = progress; 
} 

donde MyDelegate es una referencia a la función MessageHandler.

Me di cuenta de que el uso de BeginInvoke lblStatus.Text no se actualiza cuando el uso de Invoke refresca la etiqueta. Además, sé que Invoke espera a que se complete su ejecución. El caso más importante que me interesa es por qué hay una diferencia en el refrescante texto de la etiqueta en este caso.

Respuesta

8

Con Invoke, el método se ejecuta y la aplicación espera a que se complete.

Con BeginInvoke, el método se invoca asíncronamente y la aplicación continúa ejecutándose mientras se ejecuta el método al que se hace referencia en BeginInvoke.

Con BeginInvoke debe llamar a EndInvoke para obtener los resultados del método que ejecutó con BeginIvnoke.

No debe actualizar los componentes de la GUI en los métodos BeginXXX, ya que se ejecutan en otro subproceso al subproceso de la GUI, al contrario de su método Invoke. No puede acceder a los componentes de la GUI en un hilo diferente al hilo de la GUI.

Espero que esto ayude!

+12

Calling BeginInvoke no quiere decir que no se ejecuta en la interfaz de usuario hilo. Significa que se llama asincrónicamente en el hilo asociado con "this", que podría ser el hilo de UI. –

+0

entonces si no está en otro hilo, ¿cómo funciona entonces? –

+8

Desde MSDN: "Ejecuta el delegado especificado de forma asincrónica en el subproceso en el que se creó el identificador subyacente del control". Por lo tanto, si se llama desde el subproceso de interfaz de usuario, se colocará en una cola y se ejecutará cuando la interfaz de usuario lo ponga inactivo. Que será después de que el método actualmente en ejecución haya regresado. –

1

BeginInvoke ejecuta el cuerpo del método en otro hilo y permite que el hilo actual continúe. Si está tratando de actualizar directamente una propiedad de control desde otra cadena, arrojará una excepción.

+1

sí lo sé, pero ¿por qué utilizando la invocación de mi texto de la etiqueta se actualiza y utilizando BeginInvoke no es –

+0

@Niao ver la segunda frase de mi respuesta –

0

Esto básicamente se reduce a si desea o no que el control se actualice de forma síncrona o asíncrona. Todo esto depende de su situación específica.

18

Para comenzar, a partir de su enlace:

  • Control.Invoke: se ejecuta en el hilo de interfaz de usuario, pero llamar hilo de espera para la terminación antes de continuar.
  • Control.BeginInvoke: se ejecuta en el subproceso UI asíncrono, y el subproceso de llamada no espera a completarse.

y desde MSDN:

BeginInvoke Ejecuta el delegado especificado de forma asincrónica en el subproceso que identificador subyacente del control donde se creó.

Para resumir, es BeginInvoke asíncrona. Cuando se llama al BeginInvoke desde el subproceso UI, la solicitud se ejecutará en paralelo con el subproceso UI. Lo que significa que no puede ejecutarse hasta que el método que se está ejecutando vuelva a aparecer.Por lo tanto, en este caso, el cuadro de texto nunca aparecerá para actualizarse porque el bucle for no se interrumpirá, ya que el hilo de llamada no esperará a que este evento se complete antes de continuar.

Alternativamente, Invoke es synchronous. El cuadro de texto se actualizará porque el hilo de llamada esperará a que se complete la llamada antes de continuar la ejecución.

+2

Un punto menor: no se ejecuta cuando el método retorna, se hace como un incendio y se olvida: se dispara en el COM/winapi ether –

+0

Gracias por su comentario; Acabo de actualizar mi respuesta. –

5

Control.BeginInvoke no funciona en un subproceso diferente (o subprocesamiento), un delegate.BeginInvoke hace. un trazador de líneas de MSDN dice:

Ejecuta el delegado especificado de forma asincrónica en el hilo identificador subyacente del control fue creado en .

Sin embargo Control.BeginInvoke simplemente utiliza PostMessage y vuelta - sin CLR se crea Thread.

La función PostMessage coloca (mensajes) un mensaje en la cola de mensajes asociado con el hilo que creó la ventana especificada y rendimientos sin esperar a que el hilo para procesar el mensaje.

This article resume si se debe utilizar o InvokeBeginInvoke bastante bien:

que funcionan para usar, se le pregunte. Es realmente depende de su requisito. Si desea que su actualización de UI complete antes de continuar, use Invoke. Si no existe tal requerimiento, yo recomendaría usando BeginInvoke, ya que hace el hilo llamándolo aparentemente "más rápido". Sin embargo, hay algunos gotcha's con BeginInvoke.

  • Si la función que está llamando a través de accesos BeginInvoke compartió estado (estado compartido entre el hilo de interfaz de usuario y otros temas), se encuentra en problemas. El estado podría cambiar entre el momento en que llamó a BeginInvoke y cuando la función envuelta realmente se ejecuta, lo que lleva a problemas de temporización difíciles de encontrar.
  • Si está pasando parámetros de referencia a la función llamada a través de BeginInvoke, entonces debe asegurarse que nadie más modifica el objeto pasado antes de que la función finalice. Normalmente, las personas clonan el objeto antes de pasarlo a BeginInvoke, , lo que evita por completo el problema.
Cuestiones relacionadas