. NET Core BackgroundService запускается только один раз - PullRequest
0 голосов
/ 07 августа 2020

Я создаю консольное приложение. net core BackgroundService. Шаблон по умолчанию предоставляет класс Worker с методом ExecuteAsyn c (), что отлично.

Я планирую использовать Windows Task Scheduler для планирования выполнения консольного приложения один раз в день. Однако я понял, что ExecuteAsyn c () - это непрерывно выполняющийся метод. Итак, мой вопрос - как мне выполнить коды в ExecuteAsyn c () только один раз, а затем завершить работу Worker? У меня могут быть другие процессы, которые все еще работают, поэтому каждый отдельный процесс должен запускаться один раз и завершать себя.

Или BackgroundService не лучший выбор для меня?

Ответы [ 2 ]

1 голос
/ 07 августа 2020

Ответ от FlashOver верен - ExecuteAsync вызывается один раз. Не повторно.

Если вы хотите, чтобы что-то произошло в c время в IHostedService, прочтите эту статью от Microsoft.

Я вставлю код здесь на случай, если ссылка сгниет:

public class TimedHostedService : IHostedService, IDisposable
{
    private int executionCount = 0;
    private readonly ILogger<TimedHostedService> _logger;
    private Timer _timer;

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

    public Task StartAsync(CancellationToken stoppingToken)
    {
        _logger.LogInformation("Timed Hosted Service running.");

        _timer = new Timer(DoWork, null, TimeSpan.Zero, 
            TimeSpan.FromSeconds(5));

        return Task.CompletedTask;
    }

    private void DoWork(object state)
    {
        var count = Interlocked.Increment(ref executionCount);

        _logger.LogInformation(
            "Timed Hosted Service is working. Count: {Count}", count);
    }

    public Task StopAsync(CancellationToken stoppingToken)
    {
        _logger.LogInformation("Timed Hosted Service is stopping.");

        _timer?.Change(Timeout.Infinite, 0);

        return Task.CompletedTask;
    }

    public void Dispose()
    {
        _timer?.Dispose();
    }
}

Вставьте его так:

services.AddHostedService<TimedHostedService>();

Теперь имейте в виду, что если ваше приложение масштабируется по горизонтали, где у вас более одного Например, у вас будет запущено более одного таймера. Обычно это нехорошо.

В случаях, когда мне нужно, чтобы задача запускалась в определенное c время суток, я использую функцию Azure, настроенную как задание CRON.

1 голос
/ 07 августа 2020

Боюсь, вы ошибаетесь: ExecuteAsyn c (CancellationToken) зарегистрированного BackgroundService выполняется только один раз . NET Generi c Хост , который вы используете с помощью шаблона dotnet new worker.

Абстрактный класс BackgroundService - это «базовый класс для реализации длительного IHostedService". Он вызывает вашу реализацию overridden ExecuteAsyn c (CancellationToken) и передает управление Host при обнаружении оператора await. Это позволяет вызывать StartAsyn c (CancellationToken) другого IHostedService во время запуска до того, как ваш BackgroundService.ExecuteAsync(CancellationToken) завершится. Аналогичным образом, это также позволяет вызывать StopAsyn c (CancellationToken) другого IHostedService во время завершения работы до того, как ваш BackgroundService.ExecuteAsync(CancellationToken) будет корректно отменен.

Имейте в виду «repeat- until-your-BackgroundService-is-Stop "-l oop в Worker Service -Template

while (!stoppingToken.IsCancellationRequested)
{...}

, который представляет собой долго работающую службу.

Если запланированная работа только IHostedService в вашем приложении и / или это на самом деле не долго работающая служба - чего, похоже, не бывает при ежедневном выполнении - вместо того, чтобы быть производным от BackgroundService, вы можете просто реализовать IHostedService напрямую добавьте свой logi c в StartAsync и зарегистрируйте его через AddHostedService .

Когда ваша работа будет завершена, вы хотите завершить работу хоста приложения через IHostApplicationLifetime. StopApplication () . Для этого вы можете получить доступ к IHostApplicationLifetime через Constructor Injection , а затем позвонить StopApplication() после ежедневной операции в конце StartAsync. HostBuilder , созданный Host.CreateDefaultBuilder , уже добавляет Singleton ApplicationLifetime.

...