【问题标题】:Blocking call in BackgroundService makes yet another BackgroundService not runBackgroundService 中的阻塞调用使另一个 BackgroundService 无法运行
【发布时间】:2019-11-20 08:31:28
【问题描述】:

我有 2 个后台服务。

他们都调用了一个非异步的方法。这种方法我无法控制 - 我可以包装它,当然。

我通过将它们添加到服务集合来连接后台服务:

services.AddSingleton<IHostedService, BS1>();
services.AddSingleton<IHostedService, BS2>();

执行异步在它们中看起来像这样。

protected async override Task ExecuteAsync(CancellationToken stoppingToken)
{
     log.LogInformation($"Start consuming from topic: {eventStreamConsumer.Topic}");

     while (stoppingToken.IsCancellationRequested == false)
     {
           try
           {
                async...
                var consumeResult = eventStreamConsumer.Consume();

Consume 方法在这里阻塞线程,因为它不是异步的。

到目前为止,我的方法是将执行异步的内部工作封装到 Task.Factory.Start 中,但如果 Consume 没有返回,线程仍然挂起。

我想真正在一个单独的线程上运行它,但请记住执行异步依赖于类中的其他实例 - 不知道这是否会出现问题?

这种方法看起来如何?

    protected override Task ExecuteAsync(CancellationToken stoppingToken)
    {
        var task = new Task(() =>
        {
            while (stoppingToken.IsCancellationRequested == false)
            {
                try
                {
                    var consumeResult = eventStreamConsumer.Consume(); 
....
                }
                catch (Exception e)
                {
                    //swallow
                }
            }
        }, stoppingToken, TaskCreationOptions.LongRunning);

        task.Start();

        return Task.FromResult<object>(null);
    }

【问题讨论】:

  • 您应该返回您创建的任务,而不仅仅是一个空结果。

标签: c# multithreading asp.net-core .net-core async-await


【解决方案1】:

async 的工作方式正是它返回一个Task。这就是您缺少的部分:与其等待任务完成或阅读其Result,不如返回任务本身。

另外,请勿使用new Task 后跟Task.StartTask.Run 几乎是您每次都真正想要的(唯一的例外是如果您正在创建自己的任务调度程序)。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-01-25
    • 2022-07-06
    相关资源
    最近更新 更多