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 toIEnumerable<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>combinesasync(so the method body canawait) withyield return(so it can produce items one at a time), the sameyield returnyou saw withIEnumeratorin Unity coroutines, applied here to an async, awaitable sequence instead.await foreachconsumes anIAsyncEnumerable<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.