Jonwd
Jonwd

Reputation: 655

Is it recommendable to await on C# Channel.Reader.WaitToReadAsync for long periods of time?

I have a BackgroundService/IHostedService in an ASP.NET API core app with a Channel, that awaits for something else to write on the channel, so it can read it and process it. The interval of which the items are written to the channel, could be every few seconds or minutes.

This service is long lived (same lifespan as the API app), and therefore the channel as well.

// Simplified/Example code
using System.Threading.Channels;
// ...
Channel<object> channel = Channel.CreateUnbounded<object>();

protected override async Task ExecuteAsync(CancellationToken stoppingToken)
{
    while (await channel.Reader.WaitToReadAsync(stoppingToken))
    {
        while (channel.Reader.TryRead(out string item))
        {
            // Process item
        }
    }
}

My questions are:

My primary concern is that channel.Reader.WaitToReadAsync() is CPU bound and awaiting for it, for long periods of times, wastes CPU resources, and should be better off using other methods like AutoResetEvent

Upvotes: 6

Views: 3594

Answers (1)

TheGeneral
TheGeneral

Reputation: 81563

It's fine, your concerns are unfounded.

WaitToReadAsync implementation comes from the UnboundedChannelReader instantiated by Unbounded channel, which implements a special awaiter that is signaled when the writer writes.

Furthermore, since this is essentially just awaited, the thread gets reused and a continuation created until the awaiter is signaled.

The implementation of channels is about as optimised and succinct as you will get. That's not to say you can't roll-your-own using whatever other synchronization primitives you like. But the chances of you getting an implementation as streamed-lined, lightweight, reusable, cached and powerful as channels would be slim.

In short, threads are being returned to the thread pool, and no extraordinary spin-blocking or polling is performed.

Upvotes: 8

Related Questions