2011-04-28 9 views
5

He buscado y no puedo encontrar una respuesta. ¿Qué es mejor, peor, o indiferente a utilizar:Control.Invocar vs tareas con un TaskScheduler

{ 
... 
RefreshPaintDelegate PaintDelegate = new RefreshPaintDelegate(RefreshPaint); 
Control.Invoke(PaintDelegate); 
} 

protected void RefreshPaint() 
{ 
    this.Refresh(); 
} 

... o ...

Task.Factory.StartNew(() => 
{ 
    this.Refresh(); 
}, 
CancellationToken.None, 
TaskCreationOptions.None, 
uiScheduler); 

Respuesta

3

Suponiendo que uiScheduler es un programador que delegará las llamadas al hilo de la interfaz de usuario, diría que funcionalmente, usar las dos es indiferente (con la excepción de que la llamada a Control.Invocar se bloqueará hasta que la llamada finalice, mientras que la llamada a Task no podrá, sin embargo, siempre puede usar Control.BeginInvoke para hacer que sean semánticamente equivalentes).

Desde un punto de vista semántico, yo diría que usar Control.Invoke(PaintDelegate) es un enfoque mucho mejor; cuando usa un Task está haciendo una declaración implícita de que desea realizar una unidad de trabajo, y típicamente, esa unidad de trabajo tiene el contexto de ser programado junto con otras unidades de trabajo, es el programador el que determina cómo se delega ese trabajo (por lo general, tiene varios subprocesos, pero en este caso, se calcula en el hilo de la interfaz de usuario). También se debe decir que no existe un vínculo claro entre el uiScheduler y el Control que está vinculado al subproceso de interfaz de usuario que la llamada se debe hacer uno (generalmente, todos son iguales, pero es posible tener múltiples subprocesos de interfaz de usuario, aunque muy raro).

Sin embargo, en el uso de Control.Invoke, la intención de lo que quiere hacer es clara, que desea formar la llamada al hilo de interfaz de usuario que el Control está bombeando mensajes, y esto indica que la llamada a la perfección.

Creo que la mejor opción, sin embargo, es utilizar una instancia SynchronizationContext; abstrae el hecho de que necesita sincronizar llamadas a ese contexto, a diferencia de las otras dos opciones, que son ambiguas sobre la intención de la llamada (Task) o muy específicas en la forma en que se están realizando (Control.Invoke).

0

No es igual. La primera versión bloqueará el hilo de llamada hasta que el subproceso de interfaz de usuario esté listo para invocar el método. Para una versión sin bloqueo, debe usar Control.BeginInvoke, que también regresa inmediatamente.

Aparte de eso (si está comparando Tarea con un hilo de agrupación de subprocesos), hay poca diferencia en su uso.

[Editar]

En este caso, no hay ninguna diferencia entre Task.Factory.StartNew y Control.BeginInvoke (pero no Invoke como escribí más arriba), ya que sólo hay un único hilo de interfaz gráfica de usuario que puede ejecutar su código. No importa cuántas llamadas realice usando cualquiera de ellas, se ejecutarán secuencialmente cuando el hilo de la interfaz de usuario se libere.

+0

Pero ['BeginInvoke'] (http://msdn.microsoft.com/en-us/library/system.windows.forms.control.begininvoke.aspx) no lo hará. La misma sintaxis que 'Invoke', pero es asincrónica. –

+0

Consulte [¿Cuál es la diferencia entre Invoke() y BeginInvoke()] (http://stackoverflow.com/q/229554/616329) para obtener más información. –

+0

Entonces Task.Factory.StartNew() estaría más abierto al paralelismo? Programaría la actualización y permitiría que la cadena de llamadas continuase, ¿verdad? –

Cuestiones relacionadas