.net - subprocesos - metodo invoke c#
¿Cuál es la diferencia entre Invoke() y BeginInvoke() (6)
¿Se refiere a 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 asíncrona, en un subproceso de subprocesos.
- 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 utilizar BeginInvoke, aunque sospecho que estaba principalmente orientado hacia Delegate.BeginInvoke.
Para las aplicaciones de Windows Forms, sugeriría que normalmente use BeginInvoke. De esa manera, no necesita preocuparse por el interbloqueo, por ejemplo, ¡pero debe comprender que es posible que la interfaz de usuario no se haya actualizado en el momento en que la mire! En particular, no debe modificar los datos que el subproceso de la interfaz de usuario podría estar a punto de usar para fines de visualización. Por ejemplo, si tiene una persona con propiedades de Nombre y Apellido, 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 la posibilidad de que aparezca "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 corregir y evitará que su hilo de fondo no tenga que esperar sin una buena razón. Tenga en cuenta que el equipo de Windows Forms le ha garantizado que puede usar Control.BeginInvoke de manera "disparar y olvidar", es decir, sin llamar nunca a 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.
¿Solo te preguntas cuál es la diferencia entre BeginInvoke()
y Invoke()
?
Principalmente para qué se usaría cada uno.
EDITAR: ¿Cuál es la diferencia entre crear un objeto de subprocesamiento y llamar a invocar en eso y simplemente llamar a BeginInvoke()
en un delegado? ¿O son la misma cosa?
Delegate.BeginInvoke () pone en cola de forma asíncrona la llamada de un delegado y devuelve el control inmediatamente. 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.
La diferencia entre Control.Invoke()
y Control.BeginInvoke()
es,
-
BeginInvoke()
programará la acción asíncrona en el hilo de la GUI. Cuando se programa la acción asíncrona, su código continúa. Algún tiempo después (no sabes exactamente cuándo) se ejecutará tu acción asíncrona -
Invoke()
ejecutará su acción asíncrona (en el subproceso de la GUI) y esperará hasta que su acción se haya completado.
Una conclusión lógica es que un delegado que pase a Invoke()
puede tener parámetros de salida o un valor de retorno, mientras que un delegado que pase a BeginInvoke()
no puede (debe usar EndInvoke para recuperar los resultados).
Sobre la base de la respuesta de Jon Skeet, hay ocasiones en las 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 Invoke es lo que quieres.
En aplicaciones de subprocesos múltiples, es posible que no desee que un subproceso espere a que un delegado finalice la ejecución, especialmente si el delegado realiza E / S (lo que podría hacer que el delegado y su subproceso se bloqueen).
En esos casos sería útil el BeginInvoke. Al llamarlo, le dices al delegado que comience, pero tu 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 veces en que la mejora del rendimiento vale la pena.
Solo añadiendo por qué y cuándo usar Invoke ().
Tanto Invoke () como BeginInvoke () calculan el código que especifique en el subproceso del distribuidor.
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 asíncrona hasta que el usuario haya proporcionado algún tipo de retroalimentación.
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 calculado, volverá el método invoke () y podrá actuar de acuerdo con la respuesta del usuario.
Ver Pro WPF en C # capítulo 31
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 se usa Invocar , MessageBox aparece después de la suspensión de 3 segundos. Por lo tanto, muestra el efecto de una llamada asíncrona ( BeginInvoke ) y síncrona ( Invoke ).