Vb.net 创建Application.DoEvents的等待延迟替代方案
多年来,我使用以下方法在软件中造成延迟,例如:Vb.net 创建Application.DoEvents的等待延迟替代方案,vb.net,multithreading,winforms,timer,doevents,Vb.net,Multithreading,Winforms,Timer,Doevents,多年来,我使用以下方法在软件中造成延迟,例如: Wait(10000) Sub Wait(milliseconds) <here I get the current time> Do <here I loop until the current time passed in seconds and then exit this loop> Application.DoEvents() Loop End Sub
Wait(10000)
Sub Wait(milliseconds)
<here I get the current time>
Do
<here I loop until the current time passed in seconds and then exit this loop>
Application.DoEvents()
Loop
End Sub
如何在延迟后执行代码 有不同的方法可以在延迟后执行代码,也可以在延迟后异步执行代码。这里,我正在考虑一个计时器和异步/等待模式的简单实现 无论如何都应该避免调用
Application.DoEvent()
的循环
► 在一个或多个方法中使用延迟执行单个指令或代码: 您不能等待计时器,但可以使用一种方法来创建计时器,并在计时器引发其事件时执行操作,表示指定的间隔已过 下面的方法接受一个
delay
值和一个委托作为参数。延迟用于设置计时器的间隔,该操作表示计时器滴答作响时将执行的代码(这里我使用的是a,因为您似乎指的是WinForms应用程序) 当需要在延迟后执行代码时,可以调用此方法 该操作可以是一个简单的指令:在这种情况下,
label1
的文本将在5秒后设置为“完成”,而UI线程继续其操作:
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
修饰符始终应用于返回任务
或任务(某事物)
(某事物可以是方法可以返回的任何值/引用)的函数()
当Sub
(void
)方法表示事件处理程序时,它仅应用于Sub()
。
这一点非常重要,要记住并毫无例外地应用(除非您非常清楚其含义)。▬
阅读相关文档(在上一个链接中)以及以下内容:
可以使用简单的Async
方法延迟操作的执行:
Private Async Function Wait(delay As Integer, action As Action) As Task
Await Task.Delay(delay)
action?.Invoke()
End Function
这类似于计时器功能,并以类似的方式进行操作。不同之处在于,您可以wait
此方法执行它异步运行的代码,并在方法返回后等待其完成以运行其他代码。
调用线程(此处为UI线程)将继续其操作,同时等待Wait()
方法
假设,在按钮中,单击处理程序,我们希望执行一个操作(一个不返回值的方法)或一个函数(一个返回值的方法),下面的代码只应在该操作或函数返回后执行:
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秒钟,什么也不做,然后执行下面的代码
如果我们不需要执行操作,我们可以简单地使用:
我们还可以使用Async/Await等待在中运行的任务完成,调用Lambda表达式执行代码:
(举个例子,我们不应该使用线程池线程来完成如此简单的任务)
另见方法:
创建一个继续,当目标
任务完成
计时器怎么了?你试了哪个定时器?你能使用任务吗?也就是说,有一个async
函数,您可以等待并调用Task.Delay()
?您可以将延迟值和Action()
或Func()
传递给该方法(异步或非异步)。顺便说一句,如果您可以使用async stuff,Wait(5000)
可以通过Wait Task.Delay(5000)
本地设置。感谢您的响应。我从未使用过tasks或async,我在网上看到的只是C语言代码,所以我不理解。我确实尝试过计时器,但它不会循环或等待直到它完成,直到我调用计时器后它运行代码。label1.text=“DONE”只应在5秒后运行。我可以使用tasks或async thingy创建一个循环,而不冻结应用程序,同时为其提供一个应用程序。doevents替代方案,以便我可以同时执行其他操作吗?您使用的是什么版本的Visual Studio?您至少需要VS 2012才能使用async/await。我使用的是VS 2019。只是不知道如何使用aync并等待。因此,这些2我可以创建一个循环,直到计时器完成等等?主要的一点是根本不使用循环<代码>等待
允许在执行后续代码之前等待异步过程终止,而当前线程可以继续其处理。您不能使用计时器来执行此操作,但可以使用计时器来执行操作。我将发布几个例子。与此同时,看看吉米,首先,你很了不起。我的意思是你的详细回答,绝对令人惊讶!非常感谢你。我确实尝试了:DelayWithTimer(5000,Sub()Me.Label1.Text=“Done”),并注意到它的工作原理与计时器一样。它没有循环。所以技术上我可以用定时器完成同样的事情。这就是问题所在。我不想每次需要暂停时都跳转到不同的潜艇。如果我有一个SUB,它支持执行很多任务,例如使用webbrowser进行网页抓取,它需要在过程中等待几次,直到完成或加载某项操作。因此,我必须有某种类型的循环。我真的
Private Async Function Wait(delay As Integer, action As Action) As Task
Await Task.Delay(delay)
action?.Invoke()
End Function
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
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
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