Sitemap
Level Up Coding

Coding tutorials and news. The developer homepage gitconnected.com && skilled.dev && levelup.dev

Member-only story

Async Streams in C# 8+: From Task<List<T>> to IAsyncEnumerable and Channels

--

Collections are one of the fundamental pillars of every application. If you’ve ever written C# code, you’ve walked thousands of them with foreach, without even thinking about it. But what happens when the elements don't exist yet? When they arrive one page at a time from a database, from a supplier's API or from a queue? For years, the honest answer was: you wait for all of them, or you give up foreach.

public static async IAsyncEnumerable<string> ReadThisArticleAsync()
{
yield return "IAsyncEnumerable"; // the first part arrives now...
await Task.Delay(1000); // ...while the rest is still on its way
yield return "Channels";
}

In this article, we’ll explore everything there is to know about async streams, from the workarounds before C# 8 to IAsyncEnumerable<T>, the LINQ built into .NET 10 and System.Threading.Channels, and take a look at what .NET 11 adds. The synchronous half of the story, IEnumerable<T> and yield return, belongs to the Iterator pattern, which will have its own article in this series: here we start with the asynchronous half.

Note: everything here is stable, from C# 8 to .NET 10 (LTS), and the code compiles with the .NET 10 SDK. Only the last section talks about .NET 11, still a release candidate, and says so.

Press enter or click to view image in full size
C# Insights cover: the C# hexagon logo on a purple and blue wave background, with the word INSIGHTS and the title ASYNC STREAMS in large spaced capital letters.
C# Insights — Async Streams

--

--

Emanuele Longo
Emanuele Longo

Written by Emanuele Longo

.NET Software Developer driven by clean architecture and purposeful design.