Article Categories
- All Categories
-
Data Structure
-
Networking
-
RDBMS
-
Operating System
-
Java
-
MS Excel
-
iOS
-
HTML
-
CSS
-
Android
-
Python
-
C Programming
-
C++
-
C#
-
MongoDB
-
MySQL
-
Javascript
-
PHP
-
Economics & Finance
What are Async Streams in C# 8.0?
C# 8.0 introduces async streams, which enable asynchronous iteration over data that is generated or retrieved asynchronously. Unlike regular streams that return all data at once, async streams produce elements one at a time as they become available.
Async streams use the IAsyncEnumerable<T> interface and allow methods to use yield return with the async modifier. You can consume async streams using await foreach loops, which asynchronously wait for each element.
Syntax
Following is the syntax for declaring an async stream method −
static async IAsyncEnumerable<T> MethodName() {
await SomeAsyncOperation();
yield return value;
}
Following is the syntax for consuming an async stream −
await foreach (var item in MethodName()) {
// process item
}
Regular Enumerable vs Async Enumerable
The traditional IEnumerable<T> can be replaced with IAsyncEnumerable<T> when data needs to be generated asynchronously −
// Traditional synchronous approach
static IEnumerable<string> Message() {
yield return "Hello!";
yield return "World!";
}
// Async streams approach
static async IAsyncEnumerable<string> MessageAsync() {
await Task.Delay(1000);
yield return "Hello!";
await Task.Delay(1000);
yield return "World!";
}
Basic Async Stream Example
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
class Program {
public static async Task Main() {
Console.WriteLine("Starting async stream...");
await foreach (var item in MessageAsync()) {
Console.WriteLine($"Received: {item}");
}
Console.WriteLine("Stream completed.");
}
static async IAsyncEnumerable<string> MessageAsync() {
await Task.Delay(1000);
yield return "Hello!";
await Task.Delay(1000);
yield return "World!";
await Task.Delay(1000);
yield return "Done!";
}
}
The output of the above code is −
Starting async stream... Received: Hello! Received: World! Received: Done! Stream completed.
Practical Example with Data Processing
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
class Program {
public static async Task Main() {
await foreach (var number in GenerateNumbersAsync()) {
Console.WriteLine($"Processing: {number}");
}
}
static async IAsyncEnumerable<int> GenerateNumbersAsync() {
for (int i = 1; i <= 5; i++) {
// Simulate async work (e.g., database query, API call)
await Task.Delay(500);
yield return i * i; // Return square of i
}
}
}
The output of the above code is −
Processing: 1 Processing: 4 Processing: 9 Processing: 16 Processing: 25
Key Benefits
| Feature | Benefit |
|---|---|
| Memory Efficiency | Elements are generated on-demand, not stored in memory all at once |
| Responsive UI | UI remains responsive while processing async data streams |
| Real-time Processing | Process data as soon as it becomes available |
| Cancellation Support | Can be cancelled using CancellationToken |
Common Use Cases
-
API data streaming: Processing paginated API responses
-
File processing: Reading large files line by line asynchronously
-
Database queries: Streaming query results without loading all into memory
-
Real-time data: Processing live data feeds or sensor readings
Conclusion
Async streams in C# 8.0 provide an elegant way to handle asynchronous data generation and consumption using IAsyncEnumerable<T> and await foreach. They are particularly useful for scenarios where data arrives over time and you want to process it as it becomes available, improving both memory efficiency and user experience.
