await 演算子 (C# リファレンス)

await 演算子では、そのオペランドによって表わされる非同期操作が完了するまで、外側の async メソッドの評価が保留になります。 非同期操作が完了すると、await 演算子から演算の結果が返されます (結果がある場合)。 既に完了している操作を表すオペランドに await 演算子が適用されると、外側のメソッドを保留にすることなく、演算の結果がすぐに返されます。 await 演算子では、async メソッドを評価するスレッドがブロックされません。 await 演算子によって外側の async メソッドが保留になるとき、メソッドの呼び出し元にコントロールが戻ります。

次の例では、完了時にバイト配列を生成する非同期操作を表わす Task<byte[]> インスタンスが、HttpClient.GetByteArrayAsync メソッドから返されます。 操作が完了するまで、await 演算子によって DownloadDocsMainPageAsync メソッドが保留になります。 DownloadDocsMainPageAsync が保留になると、DownloadDocsMainPageAsync の呼び出し元である Main メソッドにコントロールが返されます。 DownloadDocsMainPageAsync メソッドで実行される非同期操作の結果が必要になるまで Main メソッドが実行されます。 GetByteArrayAsync ですべてのバイトが得られると、DownloadDocsMainPageAsync メソッドの残りが評価されます。 その後、Main メソッドの残りが評価されます。

using System;
using System.Net.Http;
using System.Threading.Tasks;

public class AwaitOperator
{
    public static async Task Main()
    {
        Task<int> downloading = DownloadDocsMainPageAsync();
        Console.WriteLine($"{nameof(Main)}: Launched downloading.");

        int bytesLoaded = await downloading;
        Console.WriteLine($"{nameof(Main)}: Downloaded {bytesLoaded} bytes.");
    }

    private static async Task<int> DownloadDocsMainPageAsync()
    {
        Console.WriteLine($"{nameof(DownloadDocsMainPageAsync)}: About to start downloading.");

        var client = new HttpClient();
        byte[] content = await client.GetByteArrayAsync("https://docs.microsoft.com/en-us/");

        Console.WriteLine($"{nameof(DownloadDocsMainPageAsync)}: Finished downloading.");
        return content.Length;
    }
}
// Output similar to:
// DownloadDocsMainPageAsync: About to start downloading.
// Main: Launched downloading.
// DownloadDocsMainPageAsync: Finished downloading.
// Main: Downloaded 27700 bytes.

前の例では、async Main メソッドが使用されています。これは C# 7.1 以降で可能です。 詳細は、「await operator in the Main method」 (Main メソッドの await 演算子) セクションを参照してください。

注意

非同期プログラミングの概要については、「async および await を使用した非同期プログラミング」を参照してください。 asyncawait による非同期プログラミングは、タスクベースの非同期パターンに続きます。

メソッド、ラムダ式async キーワードで修飾される匿名メソッドでのみ await 演算子を使用できます。 async メソッド内では、同期関数の本文の中、lock ステートメントのブロックの内部、安全でないコンテキストの中で await 演算子を使用することはできません。

.NET の型として TaskTask<TResult>ValueTaskValueTask<TResult> がありますが、await 演算子のオペランドはそのいずれかになります。 ただし、待機可能な式であれば await 演算子のオペランドになります。 詳細については、「C# 言語仕様」の「待機可能な式」セクションを参照してください。

t の型が Task<TResult> または ValueTask<TResult> の場合、式 await t の型は TResult になります。 t の型が Task または ValueTask の場合、await t の型は void になります。 いずれの場合も、t で例外がスローされる場合、await t で再び例外がスローされます。 例外処理の詳細については、try-catch ステートメントに関する記事の「非同期メソッドの例外」を参照してください。

async キーワードと await キーワードは、C# 5 以降で使用できます。

非同期のストリームと破棄可能

C# 8.0 以降、非同期のストリームと破棄可能を使用できます。

await foreach ステートメントを使用してデータの非同期ストリームを利用できます。 詳細については、記事「繰り返しステートメント」の「foreach ステートメント」セクション、および記事「C# 8.0 の新機能」の「非同期ストリーム」セクションを参照してください。

await using ステートメントを使用し、非同期破棄可能オブジェクト、つまり、IAsyncDisposable インターフェイスを実装する型のオブジェクトを操作します。 詳細については、「DisposeAsync メソッドの実装」記事の「非同期の破棄可能の使用」を参照してください。

Main メソッドの await 演算子

C# 7.1 以降、アプリケーション エントリ ポイントである Main メソッドから Task または Task<int> が返され、その本文で await 演算子を使用できるよう、非同期にすることができます。 以前の C# バージョンでは、非同期操作の完了を Main メソッドが待つようにする目的で、対応する async メソッドから返される Task<TResult> インスタンスの Task<TResult>.Result プロパティの値を取得できます。 値を生成しない非同期操作の場合、Task.Wait メソッドを呼び出すことができます。 言語のバージョンを選択する方法については、「C# 言語のバージョン管理」を参照してください。

C# 言語仕様

詳細については、「C# 言語仕様」の「Await 式」セクションを参照してください。

関連項目