En Visual Basic, las llamadas asíncronas y el manejo de eventos a menudo se implementan de diferentes maneras, dependiendo de la versión del lenguaje y del tipo de aplicación. En aplicaciones clásicas de WinForms en VB.NET, el manejo de la cola de eventos (event queue) generalmente implica la llamada a Application.DoEvents(). Este método permite que el controlador de eventos "libere el control", para que otros mensajes puedan ser procesados sin bloquear el hilo principal:
While loading Application.DoEvents() 'Permite que la UI responda a las acciones del usuario End While
Para la ejecución asíncrona de tareas en .NET con VB.NET se utilizan:
BackgroundWorker — un componente de WinForms para mover operaciones largas a un hilo separado con interacción segura con el hilo de la UI.Async/Await — un sistema moderno y conveniente de asincronía que apareció en .NET 4.5, permite escribir código asíncrono "como si fuera síncrono":Public Async Function LoadDataAsync() As Task Dim result As String = Await GetWebDataAsync() TextBox1.Text = result End Function
Diferencias:
DoEvents solo procesa la cola de mensajes de la UI y no crea nuevos hilos.BackgroundWorker realiza el trabajo en un hilo separado, con un evento para volver de manera segura al hilo de la UI.Async/Await implementa la asincronía, encapsulando el retorno del control al hilo de la UI.¿Cuál es el peligro de usar
DoEventsen un bucle, si se necesita cargar un archivo desde el disco y actualizar un ProgressBar?
Respuesta:
DoEvents temporalmente transfiere el control a otros eventos de Windows, pero no libera el hilo. Si se usa en bucles pesados (por ejemplo, leyendo un archivo grande mientras se actualiza la interfaz), pueden ocurrir errores inesperados: los eventos del usuario y los eventos del ratón se procesarán, lo que puede llevar a reiniciar el procesamiento o incluso a que la aplicación "se congele". Si se prevé una carga pesada, se debe utilizar BackgroundWorker o Task.
Ejemplo de un enfoque incorrecto:
For i = 1 To 1000000 ProgressBar1.Value = i / 10000 Application.DoEvents() '¡No libera el hilo principal! Next
Historia
DoEvents dentro de un largo bucle de lectura de archivos para actualizar el indicador de progreso. Como resultado, la interfaz "se colgaba": si el usuario hacía clic en el botón "Abrir" nuevamente, comenzaba un segundo proceso de lectura de archivos, mezclándose con el primero, provocando distorsión de datos y un crash de la aplicación.Historia
DoEvents en un bucle, ya que no estaba familiarizado con BackgroundWorker. Al actualizar un enorme conjunto de puntos, la aplicación comenzó a quedarse "pegada" y posteriormente "se caía" debido a un desbordamiento de la cola de mensajes de Windows.Historia
Se utilizó una llamada asíncrona a través de Async/Await, sin comprender que un trabajo largo no se puede iniciar en el hilo UI "caliente" sin Await Task.Run(...). Resultado: la interfaz no respondía a los clics y el progressbar no se actualizaba, ya que el método largo aún se ejecutaba en el hilo principal.