Channels

Async Queue (e.g. .NET Channel):

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 writing

Waiting for Channel Completion

await channel.Reader.Completion; // Waits until all items are read & channel is done

Minimal 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: