【问题标题】:BackgroundService.StartAsync, should it complete during startup or block?BackgroundService.StartAsync,它应该在启动期间完成还是阻塞?
【发布时间】:2020-09-17 07:06:41
【问题描述】:

我不知道我是否遗漏了这个难题的一部分,但就我一般习惯于使用服务而言,任何对 Start 的调用都应该始终返回,以便您了解您的服务已经开始了。

我正在学习BackgroundService:
Background tasks with hosted services in ASP.NET Core
Implement background tasks in microservices with IHostedService and the BackgroundService class

在这两个例子中,他们使用while loop 实现ExecuteAsync(由StartAsync 调用),这意味着ExecuteAsync(以及扩展名StartAsync)只会在以下情况下返回取消(例如应用关闭时)。

protected override async Task ExecuteAsync(CancellationToken stoppingToken)
{
    while (!stoppingToken.IsCancellationRequested)
    {
        _logger.LogDebug($"GracePeriod task doing background work.");

        // This eShopOnContainers method is querying a database table
        // and publishing events into the Event Bus (RabbitMQ / ServiceBus)
        CheckConfirmedGracePeriodOrders();

        await Task.Delay(_settings.CheckUpdateTime, stoppingToken);
    }
}

这与我对服务的理解相矛盾,因为您如何判断服务已成功启动与启动时挂起?

我非常感谢您对此有所了解,因为我似乎无法理解正在发生的事情,而且我似乎无法找到任何特定于此的更多信息。

编辑:添加了从BackgroundServiceExecuteAsync 的调用以进行说明:

public virtual Task StartAsync(CancellationToken cancellationToken)
{
    // Store the task we're executing
    _executingTask = ExecuteAsync(_stoppingCts.Token);

    // If the task is completed then return it,
    // this will bubble cancellation and failure to the caller
    if (_executingTask.IsCompleted)
    {
        return _executingTask;
    }

    // Otherwise it's running
    return Task.CompletedTask;
}

【问题讨论】:

  • 你能举一个例子,其中 ExecuteAsync 是“从 StartAsync 调用的”吗?
  • 啊,那个!它正在调用 ExecuteAsync,它立即返回一个任务。 StartAsync 然后继续返回 CompletedTask 本身。换句话说:对 ExecuteAsync 的调用不会阻塞。这就是为什么 ExecuteAsync 可以包含一个“(near-)infinte”循环来表示服务的生命周期。
  • 您可以将ExecuteAsync 视为返回,一旦它击中await Task.Delay。它继续运行,正如它返回的 Task 所表示的那样,但此时它不再阻塞 StartAsync
  • 啊面包屑,这太明显了,多么荷马的时刻。希望有一天我的困惑会帮助像我这样的其他悲伤麻袋。谢谢@KirkLarkin!
  • @Fildor 谢谢,我没有得到解释,因为我显然错过了使这一切正常的拼图await

标签: c# asp.net-core task-parallel-library asp.net-core-3.1 c#-8.0


【解决方案1】:

通过async 的魔力,即使ExecuteAsync 看起来是一个无限循环,它实际上会向调用者返回一个Task。延迟上的await 允许控制流离开ExecuteAsync 函数,循环的下一次迭代仅在Task 解决后运行。

如果不习惯,很容易错过。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2012-11-13
    • 1970-01-01
    • 2014-10-19
    • 1970-01-01
    • 2022-01-14
    • 2012-12-11
    • 2020-01-15
    • 1970-01-01
    相关资源
    最近更新 更多