Await 运算符 (Visual Basic)
在异步方法或 Lambda 表达式中对操作数应用 Await
运算符可暂停执行方法,直到所等待的任务完成。 任务表示正在进行的工作。
使用 Await
的方法必须具有 Async 修饰符。 使用 Async
修饰符定义并且通常包含一个或多个 Await
表达式的这类方法称为异步方法。
注意
Async
和 Await
关键字是在 Visual Studio 2012 中引入的。 有关异步编程的说明,请参阅使用 Async 和 Await 的异步编程。
通常,应用 Await
运算符的任务通常是方法调用的返回值,这种方法实现基于任务的异步模式,即 Task 或 Task<TResult>。
在以下代码中,HttpClient 方法 GetByteArrayAsync 返回 getContentsTask
,一个 Task(Of Byte())
。 当操作完成时,任务约定生成一个实际字节数组。 Await
运算符应用于 getContentsTask
以在 SumPageSizesAsync
中挂起执行,直到 getContentsTask
完成。 同时,控制权会返回给 SumPageSizesAsync
的调用方。 当 getContentsTask
完成之后,Await
表达式计算为字节数组。
Private Async Function SumPageSizesAsync() As Task
' To use the HttpClient type in desktop apps, you must include a using directive and add a
' reference for the System.Net.Http namespace.
Dim client As HttpClient = New HttpClient()
' . . .
Dim getContentsTask As Task(Of Byte()) = client.GetByteArrayAsync(url)
Dim urlContents As Byte() = Await getContentsTask
' Equivalently, now that you see how it works, you can write the same thing in a single line.
'Dim urlContents As Byte() = Await client.GetByteArrayAsync(url)
' . . .
End Function
重要
有关完整示例,请参阅演练:使用 async 和 await 访问 Web。 可以从 .NET 示例浏览器下载该示例。 示例代码位于 SerialAsyncExample 项目中。
如果 Await
应用于返回 Task(Of TResult)
的方法调用结果,则 Await
表达式的类型为 TResult。 如果 Await
应用于返回 Task
的方法调用结果,则 Await
表达式不返回值。 以下示例演示了差异。
' Await used with a method that returns a Task(Of TResult).
Dim result As TResult = Await AsyncMethodThatReturnsTaskTResult()
' Await used with a method that returns a Task.
Await AsyncMethodThatReturnsTask()
Await
表达式或声明不阻止正在执行它的线程。 而是导致编译器在 Await
表达式之后,将剩下的异步方法注册为等待任务的后续部分。 控制权随后会返回给异步方法的调用方。 任务完成时,它会调用其延续任务,异步方法的执行会在暂停的位置处恢复。
Await
表达式只出现在由 Async
修饰符标记的一个立即封闭方法体或 lambda 表达式中。 术语 Await 在该上下文中仅用作关键字。 在其他位置,它会解释为标识符。 在 Async
方法或 lambda 表达式中,Await
表达式不能出现在查询表达式中、Try…Catch...Finally 语句的 Catch
或 Finally
块中、For
或 For Each
循环的循环控制变量表达式中或者 SyncLock 语句的主体中。
例外
大多数异步方法返回 Task 或 Task<TResult>。 返回任务的属性携带有关其状态和历史记录的信息,如任务是否完成、异步方法是否导致异常或已取消以及最终结果是什么。 Await
运算符可访问这些属性。
如果等待的返回任务的异步方法会导致异常,则 Await
运算符重新引发异常。
如果等待的返回任务的异步方法取消,Await
运算符将重新引发 OperationCanceledException。
处于故障状态的单个任务可以反映多个异常。 例如,任务可能是对 Task.WhenAll 调用的结果。 等待此类任务时,等待操作仅重新引发异常之一。 但是,无法预测重新引发的异常。
有关异步方法中的错误处理的示例,请参阅 Try...Catch...Finally 语句。
示例
下面的 Windows 窗体示例阐释如何在异步方法 WaitAsynchronouslyAsync
中使用 Await
。 将该方法的行为与 WaitSynchronously
的行为进行对比。 如果没有应用 Await
运算符,WaitSynchronously
就会同步运行,而不管其定义中是否使用了 Async
修饰符和在主体中是否调用了 Thread.Sleep。
Private Async Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
' Call the method that runs asynchronously.
Dim result As String = Await WaitAsynchronouslyAsync()
' Call the method that runs synchronously.
'Dim result As String = Await WaitSynchronously()
' Display the result.
TextBox1.Text &= result
End Sub
' The following method runs asynchronously. The UI thread is not
' blocked during the delay. You can move or resize the Form1 window
' while Task.Delay is running.
Public Async Function WaitAsynchronouslyAsync() As Task(Of String)
Await Task.Delay(10000)
Return "Finished"
End Function
' The following method runs synchronously, despite the use of Async.
' You cannot move or resize the Form1 window while Thread.Sleep
' is running because the UI thread is blocked.
Public Async Function WaitSynchronously() As Task(Of String)
' Import System.Threading for the Sleep method.
Thread.Sleep(10000)
Return "Finished"
End Function