.net core Worker Service итерирует n раз, прежде чем корректно остановиться без Ctrl + C - PullRequest
0 голосов
/ 16 октября 2019

Я пытаюсь выполнить асинхронную задачу n раз, а затем аккуратно завершить ее, не нажимая Ctrl + C. Я считаю, что мне нужно использовать IHostLifetime, так как StoplationToken CancellationToken доступен только для чтения

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

Существует не так много документации относительно этого

1 Ответ

1 голос
/ 16 октября 2019

Ваш код уже принимает IHostApplicationLifetime в качестве третьего сервиса. Вы можете вызвать StopApplication(), когда хотите, чтобы хост завершил работу.

Метод StopAsync опасен, хотя и говорит, что служба остановлена, хотя base `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

...