C#
await foreach
Learn to consume an async stream with await foreach.
await foreach
await foreach consumes each element of an IAsyncEnumerable<T> in order, awaiting as it goes. Declaration: await foreach (int n in Stream()) { ... }. At each iteration it awaits the next element.
This is the async counterpart of foreach. The await keyword awaits the async production of each element. This way, while input/output is waiting the thread is not blocked; the loop ends when the stream completes.
await foreach vs foreach
Synchronous foreach works on an IEnumerable<T>; it takes elements at once. await foreach works on an IAsyncEnumerable<T>; it awaits each element async.
If you try to consume an IAsyncEnumerable with synchronous foreach you get a compile error; the element arrives inside a Task. await foreach unwraps those Tasks automatically.
Exercise Consume with await foreach
Define static async IAsyncEnumerable<string> Words(). In its body write await Task.CompletedTask;, yield return "apple";, yield return "pear";, yield return "cherry";. Make Main a static async Task Main. Count with int count = 0; await foreach (string w in Words()) { count++; } and print with Console.WriteLine(count);.
Show example solution
In Words body write await Task.CompletedTask; yield return "apple"; yield return "pear"; yield return "cherry";. Make Main static async Task Main() and write int count = 0; await foreach (string w in Words()) { count++; } Console.WriteLine(count);
Example solution:
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
class Program
{
static async IAsyncEnumerable<string> Words()
{
await Task.CompletedTask;
yield return "apple";
yield return "pear";
yield return "cherry";
}
static async Task Main()
{
int count = 0;
await foreach (string w in Words())
{
count++;
}
Console.WriteLine(count);
}
}
Test yourself
-
Complete await foreach
static async Task Consume() { ____ foreach (int n in Stream()) { Console.WriteLine(n); } }
Show answer
static async Task Consume() { await foreach (int n in Stream()) { Console.WriteLine(n); } }
-
Match foreach concepts
- foreach
- Consumes IEnumerable<T>
- await foreach
- Consumes IAsyncEnumerable<T>
- yield return
- Produces a stream element
- IAsyncEnumerable<T>
- Async stream type
-
Which type does await foreach work on?
- IEnumerable<T>
- List<T>
- Task<T>
- IAsyncEnumerable<T>
Show answer
IAsyncEnumerable<T> — Correct. await foreach requires an IAsyncEnumerable<T>.
Next lesson: yield return async