2

我在下面创建了一个示例 .NET Core 工作者服务,它只是抛出了一个异常。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;

namespace DemoWorkerService
{
    public class Worker : BackgroundService
    {
        private readonly ILogger<Worker> _logger;

        public Worker(ILogger<Worker> logger)
        {
            _logger = logger;
        }

        protected override async Task ExecuteAsync(CancellationToken stoppingToken)
        {
            while (!stoppingToken.IsCancellationRequested)
            {
                throw new Exception("My Exception");

                _logger.LogInformation("Worker running at: {time}", DateTimeOffset.Now);
                await Task.Delay(1000, stoppingToken);
            }
        }
    }
}

上述worker服务进程将因按预期抛出异常而中止。

然后我在等待语句之后更改了异常,如下所示:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;

namespace DemoWorkerService
{
    public class Worker : BackgroundService
    {
        private readonly ILogger<Worker> _logger;

        public Worker(ILogger<Worker> logger)
        {
            _logger = logger;
        }

        protected override async Task ExecuteAsync(CancellationToken stoppingToken)
        {
            while (!stoppingToken.IsCancellationRequested)
            {
                _logger.LogInformation("Worker running at: {time}", DateTimeOffset.Now);
                await Task.Delay(1000, stoppingToken);

                throw new Exception("My Exception");
            }
        }
    }
}

这次异常抛出后worker服务进程仍在进行中,我什至可以在控制台中按“Ctrl+C”停止该进程,这是日志信息:

info: DemoWorkerService.Worker[0]
      Worker running at: 01/16/2020 12:26:07 +08:00
info: Microsoft.Hosting.Lifetime[0]
      Application started. Press Ctrl+C to shut down.
info: Microsoft.Hosting.Lifetime[0]
      Hosting environment: Development
info: Microsoft.Hosting.Lifetime[0]
      Content root path: C:\MyProjects\DemoWorkerService\DemoWorkerService
info: Microsoft.Hosting.Lifetime[0]
      Application is shutting down...

这次好像worker service自己捕获了异常,所以异常没有传播到外部进程,不知道为什么worker service会有不同的行为,我把异常放在await前后?工人服务有这样两种不同的异常行为有什么原因吗?

4

1 回答 1

1

这是设计使然。BackgroundService实现IHostedService并且仅StartAsync在您的服务开始执行时返回。

如果IHostedService在 期间有任何抛出异常StartAsyncIHost则将无法启动。

因此,如果您BackgroundService在第一次等待之前抛出异常,异常将传播并使主机失败。如果你想防止这种情况,你可以简单地await Task.Yield()先打电话。

于 2020-01-16T05:38:04.373 回答