Как выполнить код после задержки.
Существуют разные методы выполнения кода после задержки или его асинхронного выполнения, независимо от задержки. Здесь я рассматриваю таймер и простые реализации шаблона Async/Await.
Цикл, который вызывает Application.DoEvent()
, следует избегать в любом случае.
► Использование таймера для задержки выполнения одной инструкции. или код в одном или нескольких методах:
Вы не можете ждать для таймера, но вы можете использовать метод, который создает таймер и выполняет действие, когда таймер вызывает свое событие, сигнализируя, что указанный интервал истек.
Следующий метод принимает в качестве аргументов значение delay
и Action делегат.
Задержка используется для установки интервала таймеров, действие представляет собой код, который будет выполняться, когда таймер тикает (я использую System.Windows.Forms.Timer здесь, поскольку вы, похоже, ссылаетесь на приложение WinForms) .
Private waitTimer As New System.Windows.Forms.Timer()
Private TimerTickHandler As EventHandler
Private Sub Wait(delay As Integer, action As Action)
waitTimer.Interval = delay
TimerTickHandler = New EventHandler(
Sub()
action.Invoke()
waitTimer.Stop()
RemoveHandler waitTimer.Tick, TimerTickHandler
End Sub)
AddHandler waitTimer.Tick, TimerTickHandler
waitTimer.Start()
End Sub
Мы можем вызвать этот метод, когда нам нужно выполнить код после задержки.
Действие может быть простой инструкцией: в этом случае текст label1
будет установлен на «Готово» через 5 секунд, в то время как поток пользовательского интерфейса продолжит свою работу:
label1.text = "About to Start..."
Wait(5000, Sub() Me.label1.Text = "Done")
Действие также может быть методом:
Private Sub SetControlText(control As Control, controlText As String)
control.Text = controlText
End Sub
' Elsewhere
Wait(5000, Sub() SetControlText(Me.label1, "Done"))
Конечно, метод SetControlText()
может выполнять более сложный код и, при желании, сам устанавливать таймер, вызывая Wait()
.
► Использование шаблона Async/Await а>.
Асинхронный метод обеспечивает удобный способ выполнения долговременной работы без блокировки потока вызывающего объекта. Вызывающий асинхронный метод может возобновить свою работу, не дожидаясь завершения асинхронного метода.
Проще говоря, добавление модификатора Async к методу, позволяет использовать Оператор ожидания для ожидания завершения асинхронной процедуры перед выполнением следующего кода, в то время как текущий поток свободен для продолжения своей обработки.
▬ Обратите внимание, что модификатор Async
всегда применяется к Function()
, возвращающему Task
или Task(Of something)
(что-то может быть любым значением/ссылкой на метод). может вернуться).
Он применяется только к Sub()
, когда метод Sub
(void
) представляет Event Handler
. Это очень важно помнить и применять без исключений (если только вы не осознаете последствия). ▬
Прочтите Документы об этом (в предыдущей ссылке) и об этом:
Асинхронизация и ожидание
Не блокировать асинхронный код
Простой метод Async
можно использовать для задержки выполнения действия:
Private Async Function Wait(delay As Integer, action As Action) As Task
Await Task.Delay(delay)
action?.Invoke()
End Function
Это похоже на функции таймера и действует аналогичным образом. Разница в том, что вы можете Await
использовать этот метод как для выполнения кода, который он запускает асинхронно, так и для ожидания его завершения для запуска другого кода после возврата метода. Вызывающий поток (здесь поток пользовательского интерфейса) продолжит свою работу, пока ожидается метод Wait()
.
Предположим, что в обработчике Button.Click
мы хотим выполнить действие (метод, который не возвращает значение) или функцию (метод, который возвращает значение), и следующий код должен выполняться только после того, как это действие или функция вернет :
Private Async Sub button1_Click(sender As Object, e As EventArgs) Handles button1.Click
Await Wait(5000, New Action(Sub() Me.label1.Text = "Done"))
Await Wait(5000, Nothing)
' (...)
' ... More code here. It will execute after the last Await completes
End Sub
Здесь мы указываем подождать 5 секунд, затем установить текст метки в значение, подождать еще 5 секунд, ничего не делая, а затем выполнить следующий код.
Если нам не нужно выполнять действие, мы можем просто использовать Task.Delay():
Private Async Sub button1_Click(sender As Object, e As EventArgs) Handles button1.Click
label1.text = "About to Start..."
Await Task.Delay(5000)
label1.Text = "Done"
' (...)
' ... More code here. It will execute after the last Await completes
End Sub
Мы также можем использовать Async/Await для ожидания завершения выполнения задачи в ThreadPool Thread, вызывающий Task.Run() для выполнения кода в лямбда-выражении:
(просто пример, мы не должны использовать ThreadPool Thread для такой простой задачи)
Private Async Sub button1_Click(sender As Object, e As EventArgs) Handles button1.Click
label1.text = "About to Start..."
Await Task.Run(Async Function()
Await Task.Delay(5000)
BeginInvoke(New Action(Sub() Me.label1.Text = "Done"))
End Function)
' (...)
' ... More code here. It will execute after the last Await completes
End Sub
См. также Task.ContinueWith() а> метод:
Создает продолжение, которое выполняется асинхронно после завершения целевой задачи.
person
Jimi
schedule
09.03.2020
async
, которую вы можете ожидать и вызыватьTask.Delay()
? Вы можете передать значение задержки иAction()
илиFunc()
методу, асинхронному или не асинхронному. Кстати, если вы можете использовать асинхронный материал,Wait(5000)
можно установить локально с помощью всего лишьAwait Task.Delay(5000)
. - person Jimi   schedule 09.03.2020Await
позволяет дождаться завершения асинхронной процедуры, прежде чем будет выполнен следующий код, в то время как текущий поток свободен для продолжения своей обработки. Вы не можете сделать это с помощью таймера, но вы можете использовать таймер для выполнения действия. Выложу пару примеров. А пока взгляните на Асинхронный программирование с помощью Async и Await. - person Jimi   schedule 10.03.2020