Как выполнить код после задержки.
Существуют различные методы для выполнения кода после задержки или асинхронно, после задержки или без нее. Здесь я рассматриваю Timer и простые реализации шаблона Async / Await.
В любом случае следует избегать l oop, который вызывает Application.DoEvent()
.
► Использование таймера для задержки выполнение одной инструкции или кода в одном или нескольких методах:
Вы не можете ожидать таймер, но вы можете использовать метод, который создает таймер и выполняет действие, когда таймер вызывает его событие, сигнализируя указанный интервал истек.
В следующем методе в качестве аргументов принимают значение delay
и действие.
Задержка используется для установки интервала таймеров, а действие представляет собой код, который будет выполняться, когда отметки времени таймера ( Я использую System. Windows .Forms.Timer здесь, так как вы, похоже, ссылаетесь на приложение WinForms).
Private Sub DelayWithTimer(delay As Integer, action As Action)
Dim localTimer = New System.Windows.Forms.Timer()
localTimer.Interval = delay
AddHandler localTimer.Tick,
Sub()
action.Invoke()
localTimer.Enabled = False
RemoveHandler localTimer.Tick, Nothing
localTimer.Dispose()
End Sub
localTimer.Enabled = True
End Sub
Мы можем вызывать этот метод в любое время, когда нам нужно выполнить код после задержки.
Мы можем задать Действие простой инструкцией:
в этом случае текст label1
будет установлен на «Готово» через 5 секунд, в то время как поток пользовательского интерфейса продолжит свои операции:
label1.text = "About to Start..."
DelayWithTimer(5000, Sub() Me.label1.Text = "Done")
Действие также может быть методом:
Private Sub SetControlText(control As Control, controlText As String)
control.Text = controlText
End Sub
' Elsewhere
DelayWithTimer(5000, Sub() SetControlText(Me.label1, "Done"))
Конечно, метод SetControlText()
может выполнять более сложный код и, при необходимости, устанавливать сам таймер, вызывая DelayWithTimer()
.
► Использование шаблона Async / Await .
Метод asyn c предоставляет удобный способ для потенциально длительной работы без блокировки потока вызывающего. Вызывающий метод asyn c может возобновить свою работу, не дожидаясь, пока метод asyn c завершит работу sh.
Проще говоря, добавление Asyn c модификатора к методу позволяет использовать оператор Await для ожидания завершения асинхронной процедуры перед выполнением следующего кода. , в то время как текущий поток может продолжить обработку.
▬ Обратите внимание, что модификатор Async
всегда применяется к Function()
, который возвращает Task
или Task(Of something)
( что-то может быть любым значением / ссылкой, которое может вернуть метод).
Это применяется только к Sub()
, только когда метод Sub
(void
) представляет Event Handler
. Это очень важно запомнить и применять без исключений (если вы не совсем понимаете последствия). 1080
Прочтите документы об этом (в предыдущей ссылке), а также:
Asyn c и Await
Не блокировать на Asyn c Код
Простой метод 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
мы хотим выполнить Action (метод, который не возвращает значение) или функцию (метод, который возвращает значение), а следующий код должен выполнить только после того, как это действие или функция вернет:
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 / Ожидание завершения выполнения задачи в потоке ThreadPool , вызов 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 () метод:
Создает продолжение, которое выполняется асинхронно после завершения целевой задачи.