C# Async Programming: Task, async/await & Cancellation

Lesson 6 of 7

Async Streams with IAsyncEnumerable

Sometimes you need to process a sequence of items that arrive over time, one at a time, page-by-page results from an API, rows streamed from a database, instead of waiting for the whole thing to complete before touching any of it.

using System;
using System.Collections.Generic;
using System.Threading.Tasks;

class Program
{
    static async Task Main()
    {
        await foreach (int number in CountUpAsync(5))
        {
            Console.WriteLine(number);
        }
    }

    static async IAsyncEnumerable<int> CountUpAsync(int max)
    {
        for (int i = 1; i <= max; i++)
        {
            await Task.Delay(500);
            yield return i;
        }
    }
}

The pieces

  • IAsyncEnumerable<T> is the asynchronous counterpart to IEnumerable<T>, a sequence where producing the next item might itself take time (a network call, a delay), instead of everything being ready up front.
  • async IAsyncEnumerable<T> combines async (so the method body can await) with yield return (so it can produce items one at a time), the same yield return you saw with IEnumerator in Unity coroutines, applied here to an async, awaitable sequence instead.
  • await foreach consumes an IAsyncEnumerable<T>, awaiting each item as it becomes available, instead of blocking until the entire sequence is ready.

When to reach for this

Use Task<List<T>> (await once, get everything) when you need the whole result before doing anything with it. Reach for IAsyncEnumerable<T> when items should be processed as they arrive, e.g. displaying search results as each page loads, instead of one blank screen until every page is in.

📝 Async Streams Quiz

Passing score: 70%
  1. 1.What does IAsyncEnumerable<T> represent?

  2. 2.____ foreach consumes an IAsyncEnumerable<T>, awaiting each item as it becomes available.

  3. 3.An async IAsyncEnumerable<T> method can use yield return, just like a synchronous iterator.