Channels
Async Queue (e.g. .NET Channel):
- Pull based
- A data structure for passing items between producers and consumers, usually in FIFO order.
- Producers write items into the queue; consumers read (or await) items as they become available.
- Designed for asynchronous, thread-safe, decoupled background processing.
- Has explicit completion and backpressure support.
- Pattern: Producer/Consumer.
Creating a Channel
using System.Threading.Channels;
// Unbounded (no item limit)
var channel = Channel.CreateUnbounded<int>();
// Bounded (limit item count)
var channel = Channel.CreateBounded<int>(capacity: 100);Writing to a Channel (Producer)
// Try synchronous write
channel.Writer.TryWrite(42);
// Asynchronous write (recommended)
await channel.Writer.WriteAsync(42);Reading from a Channel (Consumer)
// Synchronous read (returns immediately if item is there)
if (channel.Reader.TryRead(out var item)) { /* use item */ }
// Asynchronous read (waits for item)
var item = await channel.Reader.ReadAsync();Reading All Items (Recommended Pattern)
// .NET Core 3.0+ (C# 8): async stream
await foreach (var item in channel.Reader.ReadAllAsync())
{
// Process item
}Completing the Channel (Signal No More Items)
channel.Writer.Complete(); // After done writingWaiting for Channel Completion
await channel.Reader.Completion; // Waits until all items are read & channel is doneMinimal Producer-Consumer Example
var channel = Channel.CreateUnbounded<int>();
// Producer
Task.Run(async () =>
{
for (int i = 0; i < 5; i++)
{
await channel.Writer.WriteAsync(i);
}
channel.Writer.Complete();
});
// Consumer
await foreach (var item in channel.Reader.ReadAllAsync())
{
Console.WriteLine(item); // Prints 0, 1, 2, 3, 4
}Notes:
- Channels are thread-safe.
- Always complete the writer when done producing.
- Await Completion or use ReadAllAsync to fully drain.