我试图实现的是运行异步任务n次,然后优雅地完成,而无需执行ctrl + C。我相信我需要使用 IHostLifetime,因为 CancelToken stoppingToken 是只读
的public class Worker : BackgroundService
{
private readonly ILogger<Worker> _logger;
private readonly IServiceScopeFactory _scopeFactory;
public Worker(ILogger<Worker> logger, IServiceScopeFactory scopeFactory, IHostApplicationLifetime hostApplicationLifeTime)
{
_logger = logger;
_scopeFactory = scopeFactory;
}
public override Task StartAsync(CancellationToken cancellationToken)
{
return base.StartAsync(cancellationToken);
}
protected override async Task ExecuteAsync(CancellationToken stoppingToken)
{
try
{
//Running task
}
catch (Exception ex)
{
_logger.LogError(ex, "Error");
}
}
public override Task StopAsync(CancellationToken cancellationToken)
{
_logger.LogInformation($"Worker stopped at: {DateTime.Now}");
base.StopAsync(cancellationToken);
return Task.CompletedTask;
}
public override void Dispose()
{
_logger.LogInformation($"Worker disposed at: {DateTime.Now}");
base.Dispose();
}
}
关于此的文档不多
您的代码已经接受 IHostApplicationLifetime 作为其第三个服务。当您希望主机终止时,可以调用StopApplication()
。
不过,StopAsync
方法很危险 - 它说即使基础"StopAsync"没有停止,服务也已停止。这是将指示服务的取消令牌的方法,因此这可能会产生意想不到的后果。应改为:
public override Task StopAsync(CancellationToken cancellationToken)
{
_logger.LogInformation($"Worker stopped at: {DateTime.Now}");
return base.StopAsync(cancellationToken);
}
或者,更好的是:
public override Task StopAsync(CancellationToken cancellationToken)
{
await base.StopAsync(cancellationToken);
_logger.LogInformation($"Worker stopped at: {DateTime.Now}");
}
当关闭期到期且服务需要立即终止时,将发出cancellationToken
参数的信号。它不由BackgroundService
本身使用,而是传递给覆盖StopAsync
实现