El problema de la barra de progreso

El año pasado, intentando desembarazarme de una tarea tediosa que dejaba frito mi equipo, usé mi primera función recursiva con utilidad práctica. Como la tarea consumía su tiempo, tiré de un BackGroundWorker. Componente sencillo de usar y con ejemplos bastante claros en la ayuda de Visual Studio. No problem: tenía un valor de entrada pedido por el usuario, se realizaban n operaciones de forma recursiva, se obtenía un valor de salida.

Como el proceso era algo largo (mínimo unos diez segundos, pero podía llegar superar el minuto en la versión 2, que admitía de entrada una serie de valores), se me ocurrió usar una barra de progreso para mantener informado al usuario.

Entonces empezaron los problemas.

Todos los ejemplos que he visto que usan el evento ProgressChanged del BackGroundWorker para alimentar una barra de progreso presentan una serie de operaciones en secuencia con llamadas a ProgressChanged entre ellas, es decir: hago paso 1; progreso cambiado; hago paso 2; progreso cambiado… Sin embargo, mi problema era otro: tengo una instancia de mi clase de trabajo, cojo los valores del usuario (a través de DoWorkEventArgs.Argument), se los paso, y le digo “ea, majo. Tú puedes” llamando al método MiClase.HacerCurro. Ahí dentro se harán las n operaciones (recursivas), número desconocido hasta que se hagan.

Vale, pensé. Puedo provocar un evento OperaciónCompletada cada vez que complete una operación. Pero la instancia de MiClase está declarada dentro del DoWork del BackGroundWorker. No tengo acceso desde fuera. ¿Cómo lo hago?

¿Y si meto alguien que escuche en el DoWork? De esta forma tendría mi “escuchador” de eventos en el mismo hilo. Es decir, una clase, digamos Escuchante, a la que le paso mi instancia de MiClase y la del BackGroundWorker. Escuchante gestiona el evento OperacionCompletada provocando a su vez el ProgressChanged, que actualiza la barra de progreso.

No sé si será una solución muy limpia, pero funcionó.

En resumen, algo así:

Public Class Escuchante

Private WithEvents _MiClase as MiClase

Private _MiBGW as BackGroundWorker

Public Sub New(mc as MiClase, bw as BackGroundWorker)

_MiClase=mc

_MiBGW=bw

End Sub

Private Sub OpCompletada(sender as Object, e as OperacionCompletadaEventArgs) _

        Handles _MiClase.OperacionCompletada

_MiBGW.ReportProgress=e.NumOp

End Sub

End Class

Deja un comentario