ASP.Net 带任务队列的核心后台服务,是否需要 Task.Delay?

ASP.Net Core Background Service with Task Queue, does it need a Task.Delay?

我已经按照 Microsoft 文档了解如何使用任务队列实现 BackgroundService,但我注意到主循环中没有 Task.Delay,这是一个问题还是仍然 运行 还好吗?

这是有问题的服务 class:

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);
    }
}

此代码取自

https://docs.microsoft.com/en-us/aspnet/core/fundamentals/host/hosted-services?view=aspnetcore-5.0&tabs=visual-studio#queued-background-tasks

答案在于如果在队列中没有任何内容时执行这段代码会发生什么。

var workItem = await TaskQueue.DequeueAsync(stoppingToken);

答案是什么都没有发生。这行代码不会一遍又一遍地执行,直到有东西出队。这就是为什么没有必要延迟。

在某些东西出列之前它也不会阻塞。

发生的情况是执行该方法的线程被释放以执行其他操作。没有线程专用于执行 DequeueAsync。 (看到这个优秀的 post - There Is No Thread。)

当队列中出现要出列的项目时,将分配可用线程以恢复执行该方法。

DequeueAsync 仅在

时抛出异常
  • 取消令牌已取消
  • 队列的Complete方法被调用并且队列为空,这意味着您不再期望队列中出现任何内容。