我已按照 Microsoft 文档了解如何使用任务队列实现
BackgroundService
,但我注意到主循环中没有 Task.Delay
,这是一个问题还是仍然可以正常运行?
这是有问题的服务类别:
public class BackgroundTasksService : BackgroundService
{
public IBackgroundTaskQueue TaskQueue { get; }
public BackgroundTasksService(IBackgroundTaskQueue taskQueue)
{
TaskQueue = taskQueue;
}
protected override async Task ExecuteAsync(CancellationToken stoppingToken)
{
await BackgroundProcessing(stoppingToken);
}
private async Task BackgroundProcessing(CancellationToken stoppingToken)
{
while (!stoppingToken.IsCancellationRequested)
{
var workItem =
await TaskQueue.DequeueAsync(stoppingToken);
try
{
await workItem(stoppingToken);
}
catch (Exception ex)
{
}
}
}
public override async Task StopAsync(CancellationToken stoppingToken)
{
await base.StopAsync(stoppingToken);
}
}
此代码取自
答案在于如果在队列中没有任何内容时执行此代码会发生什么。
var workItem = await TaskQueue.DequeueAsync(stoppingToken);
答案是什么也没有发生。这行代码不会一遍又一遍地执行,直到某些内容出队为止。这就是为什么不需要延迟。
在某些内容出队之前它也不会阻塞。
发生的情况是执行该方法的线程被释放以执行其他操作。没有线程专门用于执行
DequeueAsync
。 (请参阅这篇优秀的帖子 - 没有线程。)
当队列中出现要出队的项目时,则会分配一个可用线程来恢复该方法的执行。
DequeueAsync
仅在以下情况下抛出异常:
Complete
方法被调用 并且队列为空,这意味着您不再期望队列中出现任何内容。