我在ASP中有一个BackgroundService/IHostedService
。NET API核心应用程序,带有Channel
,等待其他内容在通道上写入,以便它可以读取和处理它。项目写入通道的间隔可能是几秒或几分钟。
此服务使用寿命长(与API应用程序使用寿命相同(,因此也是频道。
// 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
}
}
}
我的问题是:
- 是否建议长时间等待
channel.Reader.WaitToReadAsync()
?(可能需要几分钟才能将项目写入频道( - 是否绑定了
channel.Reader.WaitToReadAsync()
I/O?(使用await
时是否释放线程?( - 使用
AutoResetEvent
并阻塞线程比使用await/async
更好吗?(没有浪费CPU周期,因为线程将进入睡眠状态(
我主要担心的是channel.Reader.WaitToReadAsync()
是CPU绑定的,并且等待它很长一段时间,浪费CPU资源,应该使用AutoResetEvent
等其他方法更好
没关系,您的担忧是没有根据的。
WaitToReadAsync
实现来自Unbounded通道实例化的UnboundedChannelReader
,该通道实现了一个特殊的awaiter,该awaiter在编写器写入时发出信号。
此外,由于本质上只是等待,线程被重用并创建一个延续,直到唤醒被发出信号。
渠道的实施是尽可能优化和简洁的。这并不是说你不能使用你喜欢的任何其他同步原语来滚动你自己的。但是,实现流式排列、轻量级、可重用、缓存和功能强大的通道的可能性很小。
简而言之,线程被返回到线程池,并且不会执行异常的旋转阻塞或轮询。