次の方法で共有


await 演算子 - タスクの完了を非同期に待機します

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

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

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://learn.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.

await 式のオペランドは、タスクが完了したときに通知を提供する必要があります。 一般に、デリゲートは、タスクが正常に完了するか失敗したときに呼び出されます。 await C# 言語仕様のセクションでは、これらの通知の実装方法について詳しく説明します。

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

注意

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

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

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

await t の型が TResult または t の場合、式 Task<TResult> の型は ValueTask<TResult> になります。 t の型が Task または ValueTask の場合、await t の型は void になります。 いずれの場合も、t で例外がスローされる場合、await t で再び例外がスローされます。

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

await foreach ステートメントを使用してデータの非同期ストリームを利用できます。 詳細については、foreachに関する記事の「 ステートメント」セクションをご覧ください。

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

Main メソッドの await 演算子

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

C# 言語仕様

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

関連項目