将 Await
运算符应用于异步方法或 lambda 表达式中的作数,以暂停方法的执行,直到等待的任务完成。 任务表示正在进行的工作。
所使用的方法 Await
必须具有 Async 修饰符。 此类方法使用 Async
修饰符定义,通常包含一个或多个 Await
表达式,称为 异步方法。
注释
Visual Studio 2012 中引入了关键字 Async
和 Await
关键字。 有关异步编程的简介,请参阅 使用 Async 和 Await 进行异步编程。
通常,应用Await
运算符的任务是从对实现 Task-Based 异步模式(即TaskTask<TResult>或异步模式)的方法的调用返回值。
在以下代码中,该方法HttpClientGetByteArrayAsync返回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
应用于返回 a Task(Of TResult)
的方法调用的结果,则 Await
表达式的类型为 TResult。 如果 Await
应用于返回 a 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... 的或Finally
块中Catch
...抓住。。。最后,在循环控件变量表达式中For
For Each
,或在 SyncLock 语句的正文中。
例外
大多数异步方法返回或 TaskTask<TResult>。 返回的任务的属性包含有关其状态和历史记录的信息,例如任务是否完成、异步方法是否导致异常或已取消,以及最终结果是什么。
Await
操作员访问这些属性。
如果等待导致异常的任务返回异步方法, Await
运算符将重新引发异常。
如果等待已取消的任务返回异步方法,则 Await
运算符将重新引发一个 OperationCanceledException。
处于故障状态的单个任务可以反映多个异常。 例如,该任务可能是对 Task.WhenAll. 的调用的结果。 等待此类任务时,await作只重新引发其中一个异常。 但是,无法预测哪些异常被重新引发。
有关异步方法中的错误处理示例,请参阅 Try...抓住。。。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