2
votes

After migration to ASP Core3 this line freezes the web app startup process (with VS debug: browser had pop up but the page loading never ends)

serviceCollection.AddHostedService<BackgroundService>();

It works in Core 2.

I can't see any breaking changes related to AddHostedService in ASP Core3 documentation:

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

It seems like blocking background server StartAsync blocks the web app startup. May be something should be configured in WebHost to make StartAsync async again?

The background service code looks like:

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
Inconsistent naming of background service?Kixoka

1 Answers

1
votes

Moving base class from IHostedService to BackgroundService and moving StartAsync to protected override async Task ExecuteAsync(CancellationToken cancellationToken) solves the problem