I am trying to develop a simple API in .NET Core that allows asynchronous processing of requests.
- Request sent to Controller
- Work scheduled on background service (IHostedService)
- Controller returns 202
- Background service performs long running operation
As the application will be running on IIS, a pool recycle can happen after the controller has returned a response. I would like to implement a way to allow the application to do a graceful shutdown - finishing it's currently executing tasks, but not accepting any new.
I am having difficulties having the graceful shutdown run to end.
For testing purposes I've simplified the StopAsync()
method, so now it only contains an async 20 second wait:
public async Task StopAsync(CancellationToken cancellationToken)
{
_logger.LogInformation("Hosted service is stopping...");
try
{
// Signal cancellation to the executing method
_stoppingTokenSource.Cancel();
_logger.LogInformation("Delay by 20s");
await Task.Delay(20000, cancellationToken);
_logger.LogInformation("Delay over");
}
finally
{
// Await all pending download requests
await Task.WhenAny(Task.WhenAll(_pendingTasks), Task.Delay(Timeout.Infinite, cancellationToken));
_logger.LogInformation("Hosted service has been stopped successfully.");
}
}
The logs only show show:
- Hosted service is stopping...
- Delay by 20s
Looking at EventViewer I can see 2 events raised for the shutdown with exactly 10 seconds in between them:
- Sent shutdown HTTP message to process '11104' and received http status '202'.
- Failed to gracefully shutdown process '11104'.
I have already tried:
Settings up shutdown timeout on Program.cs
public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>
WebHost.CreateDefaultBuilder(args)
.UseStartup<Startup>()
.UseShutdownTimeout(TimeSpan.FromMinutes(1));
Check Advanced Settings of application pool:
If you have done something similar, could you please let me know if I'm doing something wrong / point me in the right direction?
Thank you!
EDIT
While debugging the application, shutting down with CTRL + C produces the expected behaviour.