Starting with C# 8.0, you can create and consume streams asynchronously. Async streams rely on new interfaces introduced in .NET Standard 2.1 and implemented in .NET Core 3.0 to provide a natural programming model for asynchronous streaming data sources.
Prerequisites
Let's Start!
A method that returns an asynchronous stream has three properties,
- It's declared with the async modifier.
- It returns anIAsyncEnumerable<T>.
- The method contains yield return statements to return successive elements in the asynchronous stream.
Consuming an asynchronous stream requires you to add the await keyword before the foreach keyword when you enumerate the elements of the stream. Adding the await keyword requires the method that enumerates the asynchronous stream to be declared with the async modifier and to return a type allowed for an async method. Typically that means returning a
Task or
Task<TResult>. It can also be a
ValueTask or
ValueTask<TResult>. A method can both consume and produce an asynchronous stream, which means it would return an
IAsyncEnumerable<T>. The following code generates a sequence from 0 to 19, waiting 100 ms between generating each number:
- public static async IAsyncEnumerable<int> GenerateSequence()
- {
- for (int i = 0; i < 100; i++)
- {
- await Task.Delay(100);
- yield return i;
- }
- }
You would enumerate the sequence using the await foreach statement.
- await foreach (var number in GenerateSequence())
- {
- Console.WriteLine(number);
- }
I've created a new Console App for using async streams. Here is my complete program.
- using System;
- using System.Collections.Generic;
- using System.Threading.Tasks;
-
- namespace CSharp_8._0
- {
- class Program
- {
-
- public static async IAsyncEnumerable<int> GenerateSequence()
- {
- for (int i = 0; i < 100; i++)
- {
- await Task.Delay(100);
- yield return i;
- }
- }
- public static async Task PrintSequence()
- {
- await foreach (var number in GenerateSequence())
- {
- Console.WriteLine(number);
- }
- }
- static void Main(string[] args)
- {
- PrintSequence().Wait();
- }
-
- }
- }
Demo
You can also access this example code at my
GitHub repo.