Миграция в ASP CORE 3: как перенести фоновые сервисы? (служба, добавленная через AddHostedService, останавливает запуск веб-приложения) - PullRequest
2 голосов
/ 17 октября 2019

После миграции на ASP Core3 эта строка останавливает процесс запуска веб-приложения (с отладкой VS: браузер всплывал, но загрузка страницы никогда не заканчивается)

serviceCollection.AddHostedService<BackgroundService>();

Работает в Core 2.

Я не вижу каких-либо серьезных изменений, связанных с AddHostedService в документации ASP Core3:

https://docs.microsoft.com/en-us/aspnet/core/migration/22-to-30?view=aspnetcore-3.0&tabs=visual-studio

Похоже, что блокирование фонового сервера StartAsync блокирует запуск веб-приложения. Может быть, что-то должно быть настроено в WebHost для повторной асинхронной запуска StartAsync?

Код фоновой службы выглядит следующим образом:

public class MyBackgroundService : IHostedService
{
    private readonly BackgroundServiceHandle backgroundServiceHandle;
    private CancellationTokenSource tokenSource;

    public MyBackgroundService (BackgroundServiceHandle backgroundServiceHandle) => 
        this.backgroundServiceHandle = backgroundServiceHandle;


    public async Task StartAsync(CancellationToken cancellationToken)
    {
        tokenSource = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken);
        while (cancellationToken.IsCancellationRequested == false)
        {
            try
            {
                await Task.Delay(TimeSpan.FromSeconds(3), cancellationToken).ConfigureAwait(false);

               // IMPORTANT: it seems that next line blocks the web app startup, but why this works in CORE 2? 
                var taskSettings = backgroundServiceHandle.Dequeue(tokenSource.Token); 

                // the work
            }
            catch (OperationCanceledException)
            {
                // execution cancelled
            }
        }
    }

    public Task StopAsync(CancellationToken cancellationToken)
    {
        tokenSource.Cancel();
        return Task.CompletedTask;
    }
}

public sealed class BackgroundServiceHandle : IDisposable
{
    private readonly BlockingCollection<TaskSettings> blockingCollection;

    public BackgroundServiceHandle() => blockingCollection = new BlockingCollection<TaskSettings>();

    public void Enqueue(TaskSettings settings) => blockingCollection.Add(settings);

    public TaskSettings Dequeue(CancellationToken token) => blockingCollection.Take(token);

    public void Dispose()
    {
        blockingCollection.Dispose();
    }
}

1 Ответ

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

Перемещение базового класса из IHostedService в BackgroundService и перемещение StartAsync в protected override async Task ExecuteAsync(CancellationToken cancellationToken) решает проблему

...