Solución:
Quieres decir Delegate.Invoke
/BeginInvoke
o Control.Invoke
/BeginInvoke
?
-
Delegate.Invoke
: Se ejecuta de forma sincrónica, en el mismo hilo. -
Delegate.BeginInvoke
: Se ejecuta de forma asincrónica, en unthreadpool
hilo. -
Control.Invoke
: Se ejecuta en el subproceso de la interfaz de usuario, pero el subproceso de llamada espera a que se complete antes de continuar. -
Control.BeginInvoke
: Se ejecuta en el subproceso de la interfaz de usuario y el subproceso de llamada no espera a que se complete.
La respuesta de Tim menciona cuándo es posible que desee usar BeginInvoke
– aunque estaba principalmente orientado a Delegate.BeginInvoke
, Sospecho.
Para las aplicaciones de Windows Forms, le sugiero que generalmente usar BeginInvoke
. De esa manera, no tendrá que preocuparse por el interbloqueo, por ejemplo, pero debe comprender que es posible que la interfaz de usuario no se haya actualizado para la próxima vez que la vea. En particular, no debe modificar los datos que el subproceso de la interfaz de usuario podría estar a punto de usar con fines de visualización. Por ejemplo, si tiene un Person
con FirstName
y LastName
propiedades, y lo hiciste:
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 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 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 usar Control.BeginInvoke
de una manera de “disparar y olvidar”, es decir, sin llamar nunca EndInvoke
. Esto no es cierto para las llamadas asíncronas en general: normalmente, cada BeginXXX debería tener una llamada EndXXX correspondiente, generalmente en la devolución de llamada.
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 desea.
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 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 ocasiones en las 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ónica -
Invoke()
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 de salida o un valor de retorno, mientras que un delegado al que pasa BeginInvoke()
no puede (debe utilizar EndInvoke para recuperar los resultados).