关键问题是Async
不会奇迹般地让你的方法异步。它只让编译器知道你的方法将有Await
关键字,并且代码需要是converted into a state machine。 即使方法标记为Async
,任何未等待的代码也会同步执行。考虑下面的例子:
Private Async Sub Form1_Load(sender As Object,
e As EventArgs) Handles MyBase.Load
Await LongRunning1() 'opens the form, then asynchronously changes
'Text property after 2 seconds
End Sub
Private Async Function LongRunning1() As Task
Await Task.Factory.StartNew(Sub() Threading.Thread.Sleep(2000))
Me.Text = "Finished LongRunning1"
End Function
这里长时间运行的过程,Thread.Sleep
作为一个例子,被包裹成一个任务,并且有一个Await
关键字。它告诉编译器在执行下一行之前等待任务内部的语句完成。如果没有Await
,Text
属性将立即设置。
现在,假设你有一些长期运行的同步代码在你Async
方法:在这种情况下
Private Async Sub Form1_Load(sender As Object,
e As EventArgs) Handles MyBase.Load
Await LongRunning2() 'synchronously waits 2 seconds, opens the form,
'then asynchronously changes Text property after 2 seconds
End Sub
Private Async Function LongRunning2() As Task
Threading.Thread.Sleep(2000)
Await LongRunning1()
Me.Text = "Finished LongRunning2"
End Function
注意到它同步等待Thread.Sleep
完成,因此对于最终用户,您的应用程序显示为挂。底线是 - 你必须知道哪些方法调用可以长时间运行,并将它们包装到基于任务的await模型中。否则,您可能会看到您遇到的问题。
如果这听起来太复杂了,可以启动后台工作器(.NET 2.0+)或使用TPL(.NET 4.0+)来启动任务。如果您希望进入较低级别,则从.NET 1.1开始可以使用线程。然后在窗体/控件的顶部显示一些等待/进度窗口/叠加层,但功能尚不可用。检查这些了:
感谢@PanagiotisKanavos指着我在正确的方向。
检查我的编辑,我修改了PanagiotisKanavos之后的答案发表评论。 – Neolisk 2014-10-21 13:53:36