c# - Invocar y comenzar invocar
asynchronous invoke (5)
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 hilo y encontré información útil aquí: aquí
Sin embargo, cuál es la diferencia entre Invoke 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.
Noté que el uso de BeginInvoke lblStatus.Text no se actualiza cuando usar 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.
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.
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ó utilizando BeginIvnoke.
No debe actualizar los componentes de GUI en los métodos de 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!
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.
Control.BeginInvoke
no funciona en un subproceso diferente (o subproceso), un delegate.BeginInvoke sí lo hace. El trazador de líneas de MSDN dice:
Ejecuta el delegado especificado de forma asincrónica en el subproceso en el que se creó el identificador subyacente del control.
Sin embargo Control.BeginInvoke
simplemente usa PostMessage y regresa - no se crea ningún Thread
CLR.
La función PostMessage coloca (publica) un mensaje en la cola de mensajes asociada con el hilo que creó la ventana especificada y lo devuelve sin esperar a que el hilo procese el mensaje.
Este artículo resume si usar Invoke
o BeginInvoke
bastante bien:
Qué función usar, preguntas. Realmente depende de tu requerimiento. Si desea que su actualización de UI se complete antes de continuar, use Invoke. Si no hay tal requisito, sugiero usar BeginInvoke, ya que hace que el hilo lo llame aparentemente "más rápido". Sin embargo, hay algunos problemas con BeginInvoke.
- Si la función que está llamando a través de BeginInvoke accede al estado compartido (estado compartido entre el subproceso de la interfaz de usuario y otros subprocesos), tiene problemas. El estado puede cambiar entre el momento en que llamaste 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 de que nadie más modifique el objeto pasado antes de que la función se complete. Por lo general, las personas clonan el objeto antes de pasarlo a BeginInvoke, lo que evita el problema por completo.
Para comenzar, desde su enlace:
-
Control.Invoke
: se ejecuta en el subproceso de interfaz de usuario, pero el subproceso de llamada espera su finalización antes de continuar. -
Control.BeginInvoke
: se ejecuta en el subproceso UI asíncrono, y el subproceso de llamada no espera a completarse.
y de MSDN:
BeginInvoke ejecuta el delegado especificado de forma asincrónica en el subproceso en el que se creó el identificador subyacente del control.
Para resumir, BeginInvoke
es asincrónico . Cuando se BeginInvoke
desde el subproceso UI, la solicitud se ejecutará en paralelo con el subproceso UI. Lo que significa que no se ejecutará hasta después de 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 sincrónico . El cuadro de texto se actualizará porque el hilo de llamada esperará a que se complete la llamada antes de continuar la ejecución.