Home > Software engineering >  ASP.NET Core hosted service ExecuteAsync() method doesn't complete
ASP.NET Core hosted service ExecuteAsync() method doesn't complete

Time:09-22

Can anyone help me understand why "WHY DOES THIS NEVER GET CALLED?" never gets logged to the console when the application is shutdown in the following code example?

public class TestBackgroundService : BackgroundService
{
    protected override async Task ExecuteAsync(CancellationToken stoppingToken)
    {
        System.Console.WriteLine("Executing test background service...");

        await Task.Delay(Timeout.Infinite, stoppingToken);

        System.Console.WriteLine("WHY DOES THIS NEVER GET CALLED?");
    }
}

This is registered as a hosted service in the Startup class, as usual:

public void ConfigureServices(IServiceCollection services)
{
    services.AddHostedService<TestBackgroundService>();
}

My expectation was that when the application starts shutting down, the stoppingToken is triggered and the call to Task.Delay() should return, then the rest of the ExecuteAsync() method would execute during the default five second shutdown timeout, before the application forcefully shuts down.

The console shows "Executing test background service..." as expected, but not "WHY DOES THIS NEVER GET CALLED?".

For reference, the base BackgroundService class can be seen and read about here, with an example: https://docs.microsoft.com/en-us/dotnet/architecture/microservices/multi-container-microservice-net-applications/background-tasks-with-ihostedservice#implementing-ihostedservice-with-a-custom-hosted-service-class-deriving-from-the-backgroundservice-base-class

CodePudding user response:

I think there is a misunderstanding in the stoppingToken. This token is stopping the Task.Delay(...) but with an System.Threading.Tasks.TaskCanceledException So your call to the log will never be reached.

// Simplified example
public static async Task Main()
{
    var cancellationTokenSource = new CancellationTokenSource(TimeSpan.FromSeconds(2));
    // Throws after 2 seconds:
    await Task.Delay(4000, cancellationTokenSource.Token);
    // Never reached:
    Console.WriteLine("WHY DOES THIS NEVER GET CALLED?");
}

//Unhandled exception. System.Threading.Tasks.TaskCanceledException: A task was canceled.
//   at Program.Main()
//   at Program.<Main>()

Full working example can be found here

Task.Delay Documentation

CodePudding user response:

As per the MS Documentation available about 'Background tasks with hosted services in ASP.NET Core'

It is the 'StopAsync' method that gets invoked when an application begins shutting down and for you to be able to execute something at the time of the application shutting down, you need to implement an override of the StopAsync in the background service class.

So you need to add a method under the ExecuteAsync() in the same class that is something like this-

public Task StopAsync(CancellationToken stoppingToken)
{
    System.Console.WriteLine("WHY DOES THIS NEVER GET CALLED?");
    await base.StopAsync(stoppingToken);
}
  • Related