Await 演算子 (Visual Basic)
Await
演算子は、非同期のメソッドまたはラムダ式のオペランドに適用されて、待機中のタスクが完了するまでメソッドの実行を中断します。 このタスクは、進行中の作業を表します。
Await
が使用されるメソッドには Async 修飾子が必要です。 このようなメソッド (Async
修飾子を使用して定義され、通常 1 つ以上の Await
式を含むメソッド) を "非同期メソッド" と呼びます。
Note
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
修飾子で修飾されたすぐ外側のメソッドまたはラムダ式の本体でのみ使用できます。 Await という用語がキーワードとして機能するのはこのコンテキストだけです。 他の場所では、識別子として解釈されます。 Async
メソッドまたはラムダ式内では、クエリ式、Try…Catch…Finally ステートメントの Catch
ブロックまたは Finally
ブロック、For
ループまたは For Each
ループのループ コントロール変数式、または SyncLock ステートメントの本体で Await
式を使用することはできません。
例外
大半の非同期メソッドは、Task または Task<TResult> を返します。 返されるタスクのプロパティには、タスクが完了しているかどうか、非同期メソッドで例外または取り消しが発生したかどうか、最終結果など、その状態および履歴に関する情報が含まれます。 Await
演算子は、これらのプロパティにアクセスします。
タスクを返す非同期メソッドを待機しているときにそのメソッドで例外が発生した場合、Await
演算子はその例外を再スローします。
タスクを返す非同期メソッドを待機しているときにそのメソッドがキャンセルされた場合、Await
演算子は OperationCanceledException を再スローします。
障害の発生した状態にある単一のタスクで、複数の例外が反映される場合があります。 たとえば、タスクは Task.WhenAll の呼び出しの結果になることがあります。 このようなタスクを待機すると、await 操作によって 1 つの例外のみが再スローされます。 ただし、どの例外が再スローされるかを予測することはできません。
非同期メソッドのエラー処理の例については、「Try...Catch...Finally ステートメント」をご覧ください。
例
次に示す Windows フォームの例では、Await
という非同期メソッドで WaitAsynchronouslyAsync
が使用されています。 このメソッドの動作と WaitSynchronously
の動作の違いを確認します。 WaitSynchronously
には Await
演算子がないため、定義で 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
関連項目
.NET