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 呼叫的結果。 當您等候這類工作時,await 作業只會重新擲回其中一個例外狀況。 不過,您無法預測重新擲回哪個例外狀況。
如需非同步方法中錯誤處理的範例,請參閱 Try...Catch...Finally 陳述式。
範例
下列 Windows Form 範例說明如何在非同步方法 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