Что должен возвращать BackgroundService.ExecuteAsync, когда рабочий процесс управляется событиями?

Рабочая служба - это новый способ написания службы Windows в .NET Core 3.x. Рабочий класс расширяет Microsoft.Extensions.Hosting.BackgroundService и реализует ExecuteAsync. В документации по этому методу говорится:

Этот метод вызывается при запуске IHostedService. Реализация должна возвращать задачу, которая представляет время жизни выполняемых длительных операций.

Что должен возвращать этот метод, если работа, выполняемая службой, не является длительной в обычном смысле, а управляется событиями? Например, я пишу службу, которая устанавливает _ 3_. Как бы я инкапсулировал это в Task? Нет Task.Never(), так что я должен просто вернуть что-то на основе очень длинного Task.Delay(), чтобы служба не закрылась?

private async Task DoStuffAsync(CancellationToken cancel)
{
  // register events
  while(!cancel.IsCancellationRequested)
  {
    await Task.Delay(TimeSpan.FromDays(1000000), cancel);
  }
  // unregister events
}

person StackOverthrow    schedule 31.07.2020    source источник


Ответы (3)


Вы также можете использовать фактическую бесконечную задержку:

await Task.Delay(Timeout.Infinite, cancellationToken);
person Stephen Cleary    schedule 01.08.2020
comment
Не так весело, как await Eternity, но приятно знать, что это правильный подход. - person StackOverthrow; 02.08.2020

Я включил задержку в метод под названием Eternity:

private async Task Eternity(CancellationToken cancel)
{
    while (!cancel.IsCancellationRequested)
    {
        await Task.Delay(TimeSpan.FromDays(1), cancel);
    }
}

Итак, мой ExecuteAsync выглядит так:

protected override async Task ExecuteAsync(CancellationToken cancel)
{
    using (var watcher = new FileSystemWatcher())
    {
        ConfigureWatcher(watcher);
        await Eternity(cancel);
    }
}

Кажется, это работает, как ожидалось.

person StackOverthrow    schedule 31.07.2020

Если вы хотите называть это как await "Eternity" или await ("Eternity", token), если вам нужна поддержка при отмене. Мы можем использовать их с поддержкой отмены благодаря кортежам значений.

В основном вы можете ожидать чего угодно с помощью некоторых методов расширения.

Вот код:

protected override async Task ExecuteAsync(CancellationToken token)
        {
            using (var watcher = new FileSystemWatcher())
            {
                ConfigureWatcher(watcher);
                
                // Use any of these methods you'd like
                await "Eternity";
                await ("Eternity", token);
                await TimeSpan.FromDays(1);
                await (TimeSpan.FromDays(1), token);
            }
        }

public static class GetAwaiterExtensions 
    {
        public static TaskAwaiter GetAwaiter(this (TimeSpan, CancellationToken) valueTuple)
        {
            return Task.Delay((int) valueTuple.Item1.TotalMilliseconds, valueTuple.Item2)
                .GetAwaiter();
        }
        
        public static TaskAwaiter GetAwaiter(this TimeSpan timeSpan)
        {
            return Task.Delay((int) timeSpan.TotalMilliseconds)
                .GetAwaiter();
        }
        
        public static TaskAwaiter GetAwaiter(this string value)
        {
            if (value == "Eternity")
            {
                return Task.Delay(Timeout.Infinite)
                    .GetAwaiter();
            }
            
            throw new ArgumentException();
        }
        
        public static TaskAwaiter GetAwaiter(this (string, CancellationToken) valueTuple)
        {
            if (valueTuple.Item1 == "Eternity")
            {
                return Task
                    .Delay(Timeout.Infinite, cancellationToken: valueTuple.Item2)
                    .GetAwaiter();
            }
            
            throw new ArgumentException();
        }
    }
person ndogac    schedule 20.09.2020