В Visual Basic асинхронные вызовы и обработка событий часто реализуются разными способами, в зависимости от версии языка и типа приложения. В классических WinForms-приложениях VB.NET обработка очереди событий (event queue) обычно предполагает вызов Application.DoEvents(). Этот метод позволяет обработчику событий "отпустить управление", чтобы другие сообщения могли быть обработаны, не блокируя главный поток:
While loading Application.DoEvents() 'Позволяет UI реагировать на действия пользователя End While
Для асинхронного выполнения задач в .NET с VB.NET используются:
BackgroundWorker — компонент WinForms для вынесения длительных операций в отдельный поток с безопасным взаимодействием с UI-потоком.Async/Await — удобная современная система асинхронности, появившаяся в .NET 4.5, позволяет писать асинхронный код "как синхронный":Public Async Function LoadDataAsync() As Task Dim result As String = Await GetWebDataAsync() TextBox1.Text = result End Function
Различия:
DoEvents просто обрабатывает очередь сообщений UI и не создает новые потоки.BackgroundWorker относит работу в отдельный поток, с событием для безопасного возврата в UI-поток.Async/Await реализует асинхронность, при этом инкапсулирует возврат управления UI-потоку.В чем опасность использования
DoEventsв цикле, если требуется загрузить файл с диска и обновлять ProgressBar?
Ответ:
DoEvents временно передает управление другим событиям Windows, но не освобождает поток. Если использовать его в тяжелых циклах (например, чтение большого файла с одновременным обновлением интерфейса), возможны неожиданные баги: события пользователя и событий мыши будут обработаны, что может привести к повторному пуску обработки или даже "зависанию" приложения. Если предполагается тяжелая загрузка — следует использовать BackgroundWorker или Task.
Пример неправильного подхода:
For i = 1 To 1000000 ProgressBar1.Value = i / 10000 Application.DoEvents() 'Не освобождает основной поток! Next
История
DoEvents внутри длительного цикла чтения файла. В результате интерфейс "подвисал": если пользователь кликал кнопку "Открыть" ещё раз — начинался второй процесс чтения файла, вперемешку с первым, вызывая искажение данных и крэш приложения.История
DoEvents в цикле, так как не был знаком с BackgroundWorker. При обновлении огромного набора точек приложение начало залипать и впоследствии "вылетало" из-за переполнения очереди Windows сообщений.История
Использовали асинхронный вызов через Async/Await, не понимая, что долгую работу нельзя запускать в "горячем" UI-потоке без Await Task.Run(...). Итог: интерфейс не реагировал на нажатия, а прогрессбар не обновлялся, так как долгий метод всё равно выполнялся на основном потоке.