2008-10-23 17 views
335

¿Qué diferencia hay entre BeginInvoke() y Invoke()?¿Cuál es la diferencia entre Invoke() y BeginInvoke()

Principalmente para lo que se usaría cada uno.

EDITAR: ¿Cuál es la diferencia entre crear un objeto de subprocesamiento y invocar invocación sobre eso y simplemente llamar al BeginInvoke() en un delegado? ¿O son la misma cosa?

Respuesta

486

¿Quiere decir Delegate.Invoke/BeginInvoke o Control.Invoke/BeginInvoke?

  • Delegate.Invoke: se ejecuta de forma síncrona, en el mismo hilo.
  • Delegate.BeginInvoke: se ejecuta de forma asincrónica, en una secuencia de subprocesos.
  • Control.Invocar: se ejecuta en el subproceso de la interfaz de usuario, pero el subproceso de llamada espera su finalización antes de continuar.
  • Control.BeginInvoke: se ejecuta en el subproceso de la interfaz de usuario, y el subproceso de llamada no espera a completarse.

La respuesta de Tim menciona cuándo es posible que desee utilizar BeginInvoke, aunque estaba orientado principalmente a Delegate.BeginInvoke, sospecho.

Para las aplicaciones de Windows Forms, sugiero que debe generalmente use BeginInvoke. De esta forma, no tiene que preocuparse por el punto muerto, por ejemplo, pero debe entender que es posible que la interfaz de usuario no se haya actualizado en el momento en que vuelva a examinarlo. En particular, no debe modificar los datos que la secuencia de la interfaz de usuario podría utilizar para fines de visualización. Por ejemplo, si usted tiene una persona con propiedades nombre y apellidos, y se hizo:

person.FirstName = "Kevin"; // person is a shared reference 
person.LastName = "Spacey"; 
control.BeginInvoke(UpdateName); 
person.FirstName = "Keyser"; 
person.LastName = "Soze"; 

continuación, la interfaz de usuario puede bien terminar mostrando "Keyser Spacey". (Existe la posibilidad remota de que muestre "Kevin Soze" pero solo a través de la rareza del modelo de memoria).

Sin embargo, a menos que tenga este tipo de problema, Control.BeginInvoke es más fácil de hacer, y evitará hilo de fondo de tener que esperar sin una buena razón. Tenga en cuenta que el equipo de Windows Forms ha garantizado que puede usar Control.BeginInvoke de una manera "disparar y olvidarse", es decir, sin llamar siempre a EndInvoke. Esto no ocurre con las llamadas asincrónicas en general: normalmente, cada BeginXXX debe tener una llamada EndXXX correspondiente, generalmente en la devolución de llamada.

+3

Entonces, ¿por qué las personas usar Invocar sobre BeingInvoke? ¿No debería haber algunas ventajas sobre el uso de Invoke? Ambos ejecutan procesos en segundo plano, ¿solo uno está en el mismo hilo, el otro en hilo diferente? – yeeen

+2

@Jon: Mientras estoy usando Dispatcher.BeginInvoke, mi código funciona bien y en Dispatcher. Invoco mi aplicación, lo que me hace esperar unos segundos, luego inicializa todos los controles y luego se inicia. ¿Puede ayudarme a averiguar exactamente en qué lugar? atascado ? – SharpUrBrain

+0

@Todo: ¿Alguien puede dar una breve idea sobre Dispatcher.BeginInvoke y Dispatcher.Invoke? Cómo funcionan y qué hacen, todo. – SharpUrBrain

8

Delegate.BeginInvoke() colas asincrónicamente la llamada de un delegado y devuelve el control de inmediato. Al usar Delegate.BeginInvoke(), debe llamar a Delegate.EndInvoke() en el método de devolución de llamada para obtener los resultados.

Delegate.Invoke() llama sincrónicamente al delegado en el mismo hilo.

MSDN Article

41

Sobre la base de la respuesta de Jon Skeet, hay momentos en que desea invocar un delegado y esperar a que su ejecución para completar antes de que continúe el flujo actual. En esos casos, la llamada Invoke es lo que desea.

En aplicaciones de subprocesos múltiples, es posible que no desee que un subproceso espere un delegado para finalizar la ejecución, especialmente si ese delegado realiza E/S (que podría hacer que el delegado y su subproceso bloqueen).

En esos casos, el BeginInvoke sería útil. Al invocarlo, le está diciendo al delegado que comience, pero luego su hilo es libre de hacer otras cosas en paralelo con el delegado.

El uso de BeginInvoke aumenta la complejidad de su código, pero hay momentos en que el rendimiento mejorado vale la pena la complejidad.

21

La diferencia entre Control.Invoke() y Control.BeginInvoke() es,

  • BeginInvoke() programará la acción asincrónica en el subproceso de interfaz gráfica de usuario. Cuando se programa la acción asincrónica, su código continúa. Algún tiempo después (no se sabe exactamente cuándo) se ejecutará su acción asíncrona
  • Invoke() ejecutará su acción asincrónica (en el hilo de la GUI) y esperará hasta que se complete su acción.

Una conclusión lógica es que un delegado se pasa a Invoke() puede tener fuera de los parámetros o un retorno de valor, mientras que un delegado se pasa a BeginInvoke() no puede (usted tiene que utilizar EndInvoke para recuperar los resultados).

14

Sólo para dar un ejemplo corto, trabajando para ver un efecto de su diferencia

new Thread(foo).Start(); 

private void foo() 
{ 
    this.Dispatcher.BeginInvoke(DispatcherPriority.Normal, 
    (ThreadStart)delegate() 
    { 
     myTextBox.Text = "bing"; 
     Thread.Sleep(TimeSpan.FromSeconds(3)); 
    }); 
    MessageBox.Show("done"); 
} 

Si el uso BeginInvoke, de mensaje hace estallar simultánea a la actualización de texto. Si usa Invoque, MessageBox aparece después de 3 segundos de inactividad. Por lo tanto, muestra el efecto de una llamada asincrónica (BeginInvoke) y una llamada síncrona (Invoke).

6

Simplemente agregando por qué y cuándo usar Invoke().

Tanto Invoke() como BeginInvoke() calculan el código que especifique para el subproceso del asignador.

Pero a diferencia de BeginInvoke(), Invoke() detiene su hilo hasta que el despachador ejecute su código. Es posible que desee utilizar Invoke() si necesita pausar una operación asincrónica hasta que el usuario haya proporcionado algún tipo de comentario.

Por ejemplo, puede llamar a Invoke() para ejecutar un fragmento de código que muestra un cuadro de diálogo Aceptar/Cancelar. Después de que el usuario haga clic en un botón y se complete el código de referencia, volverá el método invoke() y podrá actuar en función de la respuesta del usuario.

Ver Pro WPF en C# capítulo 31

Cuestiones relacionadas