await (C# リファレンス)
await 演算子は、待機中のタスクが完了するまでメソッドの実行を中断するために、非同期メソッドのタスクに適用します。 このタスクは、進行中の作業を表します。
await を使用する非同期メソッドは、async キーワードによって変更する必要があります。 このようなメソッド (async 修飾子を使用して定義され、通常 1 つ以上の await 式を含むメソッド) を非同期メソッドと呼びます。
注意
async キーワードおよび await キーワードは、Visual Studio 2012 で導入されました。非同期プログラミングの概要については、「Async および Await を使用した非同期プログラミング (C# および Visual Basic)」を参照してください。
await 演算子を適用するタスクは通常、タスク ベースの非同期パターン を実装するメソッド呼び出しの戻り値です。 この例では、型 Task または Task の値が含まれます。
次のコードでは、HttpClient メソッドの GetByteArrayAsync が Task<byte[]> (getContentsTask) を返します。 これにより、タスクが完了したときに実際のバイト配列が生成されることが保証されます。 await 演算子が getContentsTask に適用されているため、getContentsTask が完了するまで SumPageSizesAsync の実行が中断されます。 その間、コントロールは SumPageSizesAsync の呼び出し元に戻されます。 getContentsTask が終了すると、await 式がバイト配列に評価されます。
private async Task SumPageSizesAsync()
{
// To use the HttpClient type in desktop apps, you must include a using directive and add a
// reference for the System.Net.Http namespace.
HttpClient client = new HttpClient();
// . . .
Task<byte[]> getContentsTask = client.GetByteArrayAsync(url);
byte[] urlContents = await getContentsTask;
// Equivalently, now that you see how it works, you can write the same thing in a single line.
//byte[] urlContents = await client.GetByteArrayAsync(url);
// . . .
}
重要
コード例全体については、「チュートリアル: Async と Await を使用した Web へのアクセス (C# および Visual Basic)」を参照してください。Microsoft Web サイトで開発者コード サンプル からサンプルをダウンロードできます。この例は AsyncWalkthrough_HttpClient プロジェクトにあります。
前の例で示したように、Task<TResult> を返すメソッド呼び出しの結果に await を適用する場合、await 式の型は TResult です。 Task を返すメソッド呼び出しの結果に await が適用されている場合、await 式の型は void になります。 この違いを次の例に示します。
// Keyword await used with a method that returns a Task<TResult>.
TResult result = await AsyncMethodThatReturnsTaskTResult();
// Keyword await used with a method that returns a Task.
await AsyncMethodThatReturnsTask();
await 式は、自身が実行されているスレッドをブロックするのではなく、 非同期メソッドの残りの部分が待機中のタスクの継続として登録されるようにします。 これによって、コントロールは非同期のメソッドの呼び出し元に戻されます。 タスクが完了すると、継続が呼び出され、中断したところから非同期メソッドの実行が再開されます。
await 式は、async 修飾子で修飾されたすぐ外側のメソッド、ラムダ式、または匿名メソッドの本体でのみ使用できます。 await という用語がキーワードとして機能するのはこのコンテキストだけです。 他の場所では、識別子として解釈されます。 メソッド、ラムダ式、または匿名メソッド内では、await 式は、同期関数、クエリ式、例外処理ステートメントの catch ブロックまたは finally ブロック、lock ステートメントのブロック、または unsafe コンテキストの本体では使用できません。
例外
大半の非同期メソッドは、Task または Task を返します。 返されるタスクのプロパティには、タスクが完了しているかどうか、非同期メソッドで例外または取り消しが発生したかどうか、最終結果など、その状態および履歴に関する情報が含まれます。 await 演算子は、これらのプロパティにアクセスします。
タスクを返す非同期メソッドを待機しているときにそのメソッドで例外が発生した場合、await 演算子はその例外を再スローします。
タスクを返す非同期メソッドを待機しているときにそのメソッドが取り消された場合、await 演算子は OperationCanceledException を再スローします。
障害の発生した状態にある単一のタスクで、複数の例外が反映される場合があります。 たとえば、タスクは Task.WhenAll の呼び出しの結果になることがあります。 このようなタスクを待機すると、await 操作によって 1 つの例外のみが再スローされます。 ただし、どの例外が再スローされるかを予測することはできません。
非同期メソッドのエラー処理の例については、「try-catch (C# リファレンス)」を参照してください。
使用例
次に示す Windows フォームの例では、WaitAsynchronouslyAsync という非同期メソッドで await が使用されています。 このメソッドの動作と WaitSynchronously の動作の違いを確認します。 WaitSynchronously にはタスクに適用される await 演算子がないため、定義で async 修飾子が使用されていて、本体で Thread.Sleep が呼び出されているにもかかわらず、同期的に実行されます。
private async void button1_Click(object sender, EventArgs e)
{
// Call the method that runs asynchronously.
string result = await WaitAsynchronouslyAsync();
// Call the method that runs synchronously.
//string result = await WaitSynchronously ();
// Display the result.
textBox1.Text += result;
}
// 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 Task<string> WaitAsynchronouslyAsync()
{
await Task.Delay(10000);
return "Finished";
}
// 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 Task<string> WaitSynchronously()
{
// Add a using directive for System.Threading.
Thread.Sleep(10000);
return "Finished";
}
参照
処理手順
チュートリアル: Async と Await を使用した Web へのアクセス (C# および Visual Basic)