14 Generating collections asynchronously – await foreach and IAsyncEnumerable

 

This chapter covers:

  • How await foreach works.
  • Using yield return in async methods
  • Iterating over asynchronous data using IAsyncEnumerable<T> and await foreach.

Since its inception, the C# language has featured the foreach keyword, offering a straightforward and concise way to loop through elements in a collection. With C# 2, Microsoft introduced the yield return keyword, which simplifies the dynamic generation of sequences that can be iterated with foreach (we discussed yield return back in chapter 2). In C# 8, Microsoft enhanced this functionality by allowing yield return to be used with await, allowing us to use similar syntax to write asynchronous code.

In this chapter we’ll see how the asynchronous version of foreach (called await foreach) and the asynchronous version of yield return work and how we can use them to write simple code that processes data we generate (or retrieve) asynchronously.

14.1 Iterating over an asynchronous collection

To understand how the asynchronous await foreach works we need to first take a look at the good old non-asynchronous foreach. The foreach keyword is “syntactic sugar”, it’s just a nicer way to write code relative to using more basic language features, specifically, foreach is just a nicer way to write a while loop. You can think of the compiler’s implementation of foreach as a simple text replacement, the compiler takes code like this:

14.2 Generating an asynchronous collection

14.3 Canceling an asynchronous collection

14.4 Other Options

14.5 IAsyncEnumerable<T> and LINQ

14.6 Example: Iterating over asynchronously retrieved data

14.7 Example: BlockingCollection<T>-like asynchronous queue

14.8 Summary