本文へスキップ
BecomeCoder

C#実践コース · 第1章 非同期プログラミング · レッスン8

IAsyncEnumerable と await foreach

ブラウザで完結

導入

「DBやAPIから結果が1件ずつ、非同期に届く」——そんなストリーム状のデータを自然に扱えるのがIAsyncEnumerable<T>await foreachです。yield(イテレータ)の非同期版で、全件そろうのを待たずに届いた分から処理できます。

図解

flowchart LR
    S["データ源(DB/API)"] -->|1件ずつ非同期に| Y["async + yield return"]
    Y --> AF["await foreach で受け取る"]
    AF --> P["届いた分から順に処理"]

サンプル

// await foreach: 非同期に1件ずつ届く列を受け取る
await foreach (int n in GenerateAsync())
    Console.Write($"{n} ");   // 1 2 3
Console.WriteLine();

// async + yield return で「非同期の列」を作る(yieldの非同期版)
async IAsyncEnumerable<int> GenerateAsync()
{
    for (int i = 1; i <= 3; i++)
    {
        await Task.Delay(10);   // 実際はDB/APIから1件取得するイメージ
        yield return i;
    }
}
  • IAsyncEnumerable<T>は「非同期に1件ずつ取り出せる列」
  • 受け取る側はawait foreach、作る側はasyncメソッド+yield return
  • 全件そろうのを待たず、届いた分から処理できる(大量データ・ストリーミングに有効)

演習

async IAsyncEnumerable<int> CountAsync()
{
    yield return 1;
    await Task.Delay(1);
    yield return 2;
}

// TODO: await foreach で CountAsync() の各値を "1 2 " のように空白区切りで出力してください
___
  • 期待される出力: 1 2
ヒント1を見る

await foreach (int n in CountAsync()) Console.Write($"{n} ");

ヒント2を見る

通常のforeachの前にawaitを付けるだけです

まとめ

  • IAsyncEnumerable<T>await foreachで非同期に届く列を扱える
  • 作る側はasyncメソッド+yield returnyieldの非同期版)
  • 全件待たずに処理できるのでストリーミングや大量データに向く

次章: 外部のサーバーと通信する「HTTP通信」へ進みます。

実際に動かしてみよう

本文のサンプルや演習のコードは、コードブロック右上の「コピー」ボタンでコピーして、下のエディタに貼り付ければそのまま実行できます。

C# — ブラウザ内で実行

ブラウザ内でC#を動かす環境を読み込みます(初回のみ数秒)。
スクロールして表示された時点でも自動で読み込まれます。