Почему шаблон службы worker не завершается корректно как systemd?

Я создал новый проект, используя шаблон службы worker, и добавил две строки.

Один дополнительный вывод журнала в worker после остановки:

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

И один в Program.cs для поддержки systemd:

    public static IHostBuilder CreateHostBuilder(string[] args) =>
        Host.CreateDefaultBuilder(args)
            .UseSystemd() // <---- systemd support
            .ConfigureServices((hostContext, services) =>
            {
                services.AddHostedService<Worker>();
            });

Я могу запускать и останавливать службу на моем сервере ubuntu, но в выводе journalctl не появляется дополнительная строка журнала:

worker[25468]: WorkerService.Worker[0] Worker running at: 02/10/2021 23:07:34 +01:00
systemd[1]: Stopping Long running service/daemon created from .NET worker template...
worker[25468]: Microsoft.Hosting.Lifetime[0] Application is shutting down...
// here I would expect "Worker stopped."
systemd[1]: Stopped Long running service/daemon created from .NET worker template.

Как я могу убедиться, что моя фоновая служба работает до завершения до остановки службы?

Я нашел этот очень похожий вопрос, но, к сожалению, на него нет удовлетворительного ответа: . NET core BackgroundService не завершается корректно как демон

Но я не могу поверить, что на этот вопрос нет однозначного ответа.

ОБНОВЛЕНИЕ:

Я нашел способ изящно закрыть службу. Вместо того, чтобы ждать, пока сработает stoppingToken в ExecuteAsync(), я проверяю флаг, должна ли служба перестать работать, который установлен в методе StopAsync(). Затем с помощью ManualResetEvent я могу решить, должна ли служба ждать, пока Backgroundservice завершит свою работу и корректно завершит свою работу, или она должна принудительно завершить работу по истечении заданного тайм-аута. Вероятно, это не самый элегантный способ сделать это, но, похоже, он делает то, что я хочу.

    private bool _stopRunning;
    private ManualResetEvent _mre;
    private int _graceperiod = 5000;
    protected override async Task ExecuteAsync(CancellationToken stoppingToken)
    {
        _stopRunning = false;
        _mre = new ManualResetEvent(false);
        int item = 1;
        while (!_stopRunning)
        {
            _logger.LogInformation("Working on item " + item);
            await Task.Delay(3000);
            _logger.LogInformation("still working on item " + item);
            await Task.Delay(3000);
            _logger.LogInformation("Finished working on item " + item);
            item++;
        }

        _logger.LogInformation("Worker stopped.");
        _mre.Set();
    }

    public override async Task StopAsync(CancellationToken cancellationToken)
    {
        _stopRunning = true;
        bool gracefulShutdown = _mre.WaitOne(_graceperiod);
        if (gracefulShutdown)
        {
            _logger.LogInformation("Shut down service gracefully");
        }
        else
        {
            _logger.LogInformation("Force shut down service");
        }
        await base.StopAsync(cancellationToken);
    }

Я все же хотел бы понять, как должен срабатывать stoppingToken.


person Ben    schedule 10.02.2021    source источник


Ответы (1)


Вы можете проверить StopAsync метод класса BackgroundService. Нравится

public override Task StopAsync(CancellationToken cancellationToken)
{
    // add your logging or anything extra here
    return base.StopAsync(cancellationToken);
}
person Muhammad Hannan    schedule 11.02.2021
comment
Я экспериментировал с функцией StopAsync (). Но как только вызывается base.StopAsync (), служба некорректно завершает работу. Я хотел бы каким-то образом вызвать stoppingToken в ExecuteAsync (), но я не понимаю базовый механизм. - person Ben; 11.02.2021