Varios hilos de ejecución (multithreading) en C# .NET con BackgroundWorker

Trabajar con varios hilos (threads) es una forma de mejorar el rendimiento computacional, así como delegar operaciones sin bloquear el hilo principal de ejecución.

La ejecución y gestión de varios hilos es una tarea compleja y complicada incluso con las clases que describo a continuación.

BackgroudWorker es una forma relativamente sencilla de implementar la ejecución de múltiples hilos en aplicaciones WinForms. La clase tiene algunas carencias, que pueden ser suplidas con el uso directo de la clase Thread.

Una aplicación práctica de un bgWorker, por ejemplo, es delegar una tarea a un segundo hilo de ejecución mientras el hilo principal ejecuta la interfaz gráfica. El típico caso de tener una barra de progreso de un proceso y no bloquear la aplicación mientras se está haciendo esa tarea pesada.

Lo primero que hacemos para hacer uso de esta clase es instanciarla:

Seguidamente inicializamos de acuerdo a nuestro interés:

Finalmente lanzamos la ejecución asíncrona del segundo hilo:

En este caso:

1. Reporta el progreso (ideal para nuestra barra de progreso)
2. Permite cancelar el segundo hilo de ejecución
3. bw_DoWork es el método que se ejecutará una vez lanzemos el segundo hilo.
4. bw_ProgressChanged es el evento que se dispara si el bw informa de un cambio en el progreso
5. bw_RunWorkerCompleted es el evento que se dispara si el bw informa de que ha acabado.

A continuación, un ejemplo del método bw_DoWork que se ejecutará en el segundo hilo:

Nos fijamos en que podemos pasar argumentos del hilo principal al hilo secundario de la siguiente forma:

Si necesitamos pasar más argumentos, tendremos que crearnos una estructura de datos como ,por ejemplo, una lista de objetos:

y lo recogemos en DoWork del mismo modo con:

Es posible que desde el segundo hilo de ejecución, queramos actualizar alguno de los controles de la interfaz del hilo principal (al estar en un hilo diferente no tendremos acceso directo). Esto lo podemos hacer de la siguiente forma:

Supongamos ahora que queremos reportar el progreso en, DoWork colocaríamos:

Enviamos la variable “i”, porque es la que nos dirá como va la ejecución del búcle. Una vez se de esta situación se disparará el evento bw_ProgressChanged, desde donde podremos hacer los cambios oportunos:

Finalmente, una vez nuestro proceso finalice se disparará el evento bw_RunWorkerCompleted, donde podremos ejecutar varias acciones, en función de como haya concluído el hilo secundario:

Se puede ver más información al respecto en la página dedicada de la Microsoft Developer Network

Saludos,