Respuestas:
¿Te refieres a Delegate.Invoke
/ BeginInvoke
o Control.Invoke
/ BeginInvoke
?
Delegate.Invoke
: Se ejecuta sincrónicamente en el mismo hilo.Delegate.BeginInvoke
: Se ejecuta de forma asíncrona en un threadpool
hilo.Control.Invoke
: 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 su finalización.La respuesta de Tim menciona cuándo es posible que desee usar BeginInvoke
, aunque Delegate.BeginInvoke
sospecho que estaba orientado principalmente a eso.
Para las aplicaciones de formularios Windows Forms, sugeriría que normalmente debería usar BeginInvoke
. De esa manera, no necesita preocuparse por el punto muerto, por ejemplo, ¡pero debe comprender que la UI puede no haberse actualizado para la próxima vez que la mire! En particular, no debe modificar los datos que el subproceso de interfaz de usuario podría estar a punto de utilizar para fines de visualización. Por ejemplo, si tiene un Person
con FirstName
y LastName
propiedades, y lo hizo:
person.FirstName = "Kevin"; // person is a shared reference
person.LastName = "Spacey";
control.BeginInvoke(UpdateName);
person.FirstName = "Keyser";
person.LastName = "Soze";
Entonces la interfaz de usuario puede terminar mostrando "Keyser Spacey". (Existe una posibilidad externa de que pueda mostrar "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 hacerlo bien y evitará que su hilo de fondo tenga que esperar sin una buena razón. Tenga en cuenta que el equipo de Windows Forms ha garantizado que puede usarlo Control.BeginInvoke
de manera "dispare y olvide", es decir, sin tener que llamar EndInvoke
. Esto no es cierto para las llamadas asíncronas en general: normalmente cada BeginXXX debe tener una llamada EndXXX correspondiente, generalmente en la devolución de llamada.
Sobre la base de la respuesta de Jon Skeet, hay momentos en que desea invocar a un delegado y esperar a que se complete su ejecución antes de que continúe el hilo actual. En esos casos, la llamada de invocación es lo que desea.
En aplicaciones de subprocesos múltiples, es posible que no desee que un subproceso espere que un delegado finalice la ejecución, especialmente si ese delegado realiza E / S (lo que podría hacer que el delegado y su subproceso se bloqueen).
En esos casos, BeginInvoke sería útil. Al llamarlo, 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 diferencia entre Control.Invoke()
y Control.BeginInvoke()
es,
BeginInvoke()
programará la acción asincrónica en el hilo de la GUI. Cuando se programa la acción asincrónica, su código continúa. Algún tiempo después (no sabe exactamente cuándo) se ejecutará su acción asincrónicaInvoke()
ejecutará su acción asincrónica (en el hilo de la GUI) y esperará hasta que su acción se haya completado.Una conclusión lógica es que un delegado al que pasa Invoke()
puede tener parámetros fuera o un valor de retorno, mientras que un delegado al que pasa BeginInvoke()
no puede (debe usar EndInvoke para recuperar los resultados).
Solo para dar un breve ejemplo de trabajo para ver el 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 usa BeginInvoke , MessageBox aparece simultáneamente a la actualización de texto. Si usa Invoke , MessageBox aparece después de 3 segundos de suspensión. Por lo tanto, muestra el efecto de una llamada asincrónica ( BeginInvoke ) y una síncrona ( Invoke ).
Delegate.BeginInvoke () pone en cola asíncronamente la llamada de un delegado y devuelve el control de inmediato. Cuando use 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.
Simplemente agregue por qué y cuándo usar Invoke ().
Tanto Invoke () como BeginInvoke () reúnen el código que especifique en el hilo del despachador.
Pero a diferencia de BeginInvoke (), Invoke () detiene su hilo hasta que el despachador ejecuta 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 muestre un cuadro de diálogo Aceptar / Cancelar. Después de que el usuario hace clic en un botón y se completa su código ordenado, el método invoke () volverá y usted puede actuar según la respuesta del usuario.
Ver Pro WPF en C # capítulo 31