Skip to content
Channels and Concurrent Producer/Consumer
step 1/5

Reading — step 1 of 5

Learn

~1 min readMemory and Performance

System.Threading.Channels provides high-performance producer/consumer queues — replacing many uses of BlockingCollection<T>.

using System.Threading.Channels;

var channel = Channel.CreateUnbounded<int>();

// Producer:
await Task.Run(async () => {
    for (int i = 0; i < 10; i++) {
        await channel.Writer.WriteAsync(i * i);
    }
    channel.Writer.Complete();   // no more items
});

// Consumer:
await foreach (var value in channel.Reader.ReadAllAsync()) {
    Console.WriteLine(value);
}

Channel types:

  • Unbounded — backed by ConcurrentQueue, no size limit (memory only). Use cautiously.
  • Bounded — limited to N items, with a strategy when full:
    • BoundedChannelFullMode.Wait — producer blocks (default)
    • DropOldest — discards old items to make room
    • DropNewest — discards what was about to be added
    • DropWrite — silently fails the write
var bounded = Channel.CreateBounded<Work>(new BoundedChannelOptions(100) {
    FullMode = BoundedChannelFullMode.Wait
});

SingleReader / SingleWriter — performance hints. If you guarantee only one reader (or writer) thread, the channel uses a faster code path.

Benefits over BlockingCollection:

  • Async-native: await ReadAsync() doesn't block a thread
  • No locks under contention
  • Backpressure built in (bounded)

Pattern: pipeline of stages:

var parsed = Channel.CreateBounded<ParseResult>(100);
var processed = Channel.CreateBounded<ProcessedItem>(100);

// Stage 1: read input -> parsed
var parser = Task.Run(async () => {
    await foreach (var line in ReadLinesAsync()) {
        await parsed.Writer.WriteAsync(Parse(line));
    }
    parsed.Writer.Complete();
});

// Stage 2: parsed -> processed
var worker = Task.Run(async () => {
    await foreach (var p in parsed.Reader.ReadAllAsync()) {
        await processed.Writer.WriteAsync(Process(p));
    }
    processed.Writer.Complete();
});

Classic dataflow pipeline — and it composes naturally with await foreach.

Discussion

Ask a question, share an insight, or help someone who’s stuck.

Sign in to post a comment or reply.

Loading…