Application.DoEvents, когда нужно, а когда нет?
-
12-09-2019 - |
Вопрос
В чем необходимость использования Application.DoEvents
и когда нам следует его использовать?
Решение
Application.DoEvents
обычно используется для обеспечения периодической обработки событий при выполнении какой-либо длительной операции в потоке пользовательского интерфейса.
Лучшее решение — просто не делать этого.Выполнять длительные операции в отдельных потоках, сортируя их в поток пользовательского интерфейса (либо с помощью Control.BeginInvoke
/Invoke
или с BackgroundWorker
), когда вам нужно обновить пользовательский интерфейс.
Application.DoEvents
вводит возможность повторного входа, что может привести к очень трудным для понимания ошибкам.
Другие советы
Windows поддерживает очередь для хранения различных событий, таких как щелчок, изменение размера, закрытие и т. д.Пока элемент управления отвечает на событие, все остальные события остаются в очереди.Поэтому, если вашему приложению требуется слишком много времени для обработки нажатия кнопки, остальная часть приложения может зависнуть.Следовательно, возможно, что ваше приложение не отвечает, пока оно выполняет тяжелую обработку в ответ на событие.Хотя в идеале вам следует выполнять тяжелую обработку асинхронно, чтобы гарантировать, что пользовательский интерфейс не зависает, быстрое и простое решение — просто периодически вызывать Application.DoEvents(), чтобы разрешить отправку ожидающих событий в ваше приложение.
В хорошем Windows-приложении конечному пользователю не нравится, когда какая-либо форма приложения зависает при выполнении более крупных/тяжеловесных операций.Пользователь всегда хочет, чтобы приложение работало плавно и быстро, а не зависал пользовательский интерфейс.Но после поиска в Google я обнаружил, что Application.DoEvents() не рекомендуется использовать в приложении чаще, поэтому вместо этих событий лучше использовать BackGround Worker Thread для выполнения длительной задачи без зависания окон.
Вы можете получить лучшее представление, если посмотрите на практике.Просто скопируйте следующий код и проверьте приложение с добавлением Application.DoEvents() и без него.
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
For i As Integer = 0 To 1000
System.Threading.Thread.Sleep(100)
ListBox1.Items.Add(i.ToString())
Application.DoEvents()
Next
End Sub
Имхо, вам не следует никогда его использовать, так как вы можете получить очень неожиданное поведение.Только что сгенерированный код в порядке.Например, вы снова выполняете обработчик событий, в котором вы сейчас находитесь, потому что пользователь дважды нажал клавишу и т. д. и т. п.Если вы хотите обновить элемент управления для отображения текущего процесса, вам следует явно вызвать .Update для этого элемента управления вместо вызова Application.DoEvents.