WPF BackgroundWorker vs. Dispatcher

En mi aplicación WPF necesito hacer una operación asincrónica, entonces necesito actualizar la GUI. Y esto lo tengo que hacer muchas veces en diferentes momentos con diferentes oparaciones. Conozco dos formas de hacer esto: Dispatcher y BackgroundWorker.

Porque cuando lo elijo será difícil para mí volver, te pregunto: ¿qué es mejor? ¿Cuáles son las razones para elegir una en lugar de la otra?

¡Gracias! Pileggi

La principal diferencia entre el Dispatcher y otros métodos de subprocesamiento es que el Dispatcher no es en realidad multiproceso. El Dispatcher rige los controles, que necesitan un único hilo para funcionar correctamente; el método BeginInvoke del Dispatcher pone en cola los eventos para su posterior ejecución (dependiendo de la prioridad, etc.), pero aún en el mismo hilo.

Por otro lado, BackgroundWorker ejecuta el código al mismo tiempo que se invoca, en un hilo separado. También es más fácil de usar que los hilos verdaderos porque sincroniza automáticamente (al menos creo que recuerdo esto correctamente) con el hilo principal de una aplicación, el responsable de los controles y la cola de mensajes (el hilo Dispatcher en el caso de WPF y Silverlight), por lo que no es necesario utilizar Dispatcher.Invoke (o Control.Invoke en WinForms) al actualizar los controles del subproceso en segundo plano, aunque es posible que no siempre se recomiende.

Como dijo Reed, Task Parallel Library es una excelente opción alternativa.

Editar: más observaciones.

Como dije antes, el Dispatcher no es realmente multiproceso; solo da la ilusión de ello, porque ejecuta delegates que pasas a él en otro momento. Usaría el despachador solo cuando el código realmente solo trata con el aspecto de vista de una aplicación, es decir, controles, páginas, ventanas y todo eso. Y, por supuesto, su uso principal es desencadenar acciones de otros hilos para actualizar los controles correctamente o en el momento adecuado (por ejemplo, establecer el foco solo después de que algún control se haya renderizado / distribuido completamente se logra más fácilmente usando Dispatcher, porque en la representación de WPF no es exactamente determinista).

BackgroundWorker puede hacer que el código multiproceso sea mucho más simple de lo que normalmente es; es un concepto simple de comprender, y sobre todo (si tiene sentido) puede derivar trabajadores personalizados de él, que pueden ser clases especializadas que realizan una única tarea de forma asincrónica, con propiedades que pueden funcionar como parámetros, notificación de progreso y cancelación, etc. Siempre encontré a BackgroundWorker de gran ayuda (excepto cuando tuve que derivar de él para mantener la Cultura del hilo original para mantener la localización correctamente: P)

La ruta más poderosa pero también difícil es usar el nivel más bajo disponible, System.Threading.Thread; sin embargo, es tan fácil equivocarse que no es realmente recomendable. La progtwigción multiproceso es difícil , eso es un hecho. Sin embargo, hay una gran cantidad de buena información si quieres entender todos los aspectos: este excelente artículo de nuestro buen compañero Jon Skeet salta inmediatamente a la mente (la última página del artículo también tiene un buen número de enlaces muy interesantes).

En .Net 4.0 tenemos una opción diferente, Task Parallel Library. Todavía no he trabajado mucho, pero por lo que he visto es impresionante (y PLINQ es simplemente genial). Si tiene la curiosidad y los recursos para aprenderlo, eso es lo que recomendaría (después de todo, no debería tomar tanto para aprender).

BackgroundWorker es agradable si está realizando una única operación, que proporciona notificaciones de progreso y un evento de finalización. Sin embargo, si va a ejecutar la misma operación varias veces o varias operaciones, necesitará más de un BackgroundWorker. En este caso, puede ser engorroso.

Si no necesita los eventos de progreso, entonces usar ThreadPool y Dispatcher puede ser más simple, especialmente si va a realizar bastantes operaciones diferentes.

Sin embargo, si C # 4 es una opción, el uso de la Biblioteca de tareas paralelas también es una gran opción. Esto le permite usar la configuración de tareas de continuación utilizando el SynchronizationContext actual, que proporciona un modelo mucho más simple y limpio en muchos casos. Para obtener más información, consulte la publicación de mi blog sobre el tema.