Lets have this WorkerSample application:
Program.cs
using WorkerSample;
IHost host = Host.CreateDefaultBuilder(args)
.ConfigureServices(services =>
{
services.AddHostedService<Worker>();
})
.Build();
host.Run();
Console.WriteLine("Program terminated");
Worker.cs:
namespace WorkerSample;
public class Worker : BackgroundService
{
protected override async Task ExecuteAsync(CancellationToken stoppingToken)
{
Console.WriteLine("Worker executing ...");
try
{
await Task.Delay(Timeout.Infinite, stoppingToken);
}
catch (OperationCanceledException) { }
try
{
await Task.Delay(25000);
Console.WriteLine("I have shut down gracefully");
}
catch (Exception ex)
{
Console.WriteLine($"Error shutting down gracefully \n {ex.ToString()}");
}
finally
{
Console.WriteLine("Finally block called");
}
}
}
If I run this app on .NET 6.0 and press Ctrl+C:
with await Task.Delay(5000)
I see the following output:
Worker executing ...
I have shut down gracefully
Finally block called
Program terminated
So I have at least 5 seconds for shutting down gracefully.
With await Task.Delay(6000)
I see the following output:
Worker executing ...
Program terminated
So I have less than 6 seconds for shutting down gracefully
In .NET 7.0 things changed. I have al least 25 seconds and less than 30 seconds for shutting down gracefully.
How much time do I have for shutting down gracefully? Does it depend only .NET version? Is it configurable?
HostOptions.ShutdownTimeout
stores the default timeout for IHost.StopAsync
method. Default timeout is 5 seconds for .NET Core and .NET 5 and 30 seconds for .NET 6 and .NET 7.
StopAsync
is called when the application receives the shut down (SIGTERM
) signal, for example when you push CTRL+C
in the console window, or the app is stopped by the host system. This allows you to close any open connections, dispose resources, and generally clean up your class as required.
HostOptions
isn't explicitly configured anywhere by default, so you will need to configure it manually. For example, the following config increases the timeout to 15s:
IHost host = Host.CreateDefaultBuilder(args)
.ConfigureServices(services =>
{
services.AddHostedService<Worker>();
services.Configure<HostOptions>(
opts => opts.ShutdownTimeout = TimeSpan.FromSeconds(15));
})
.Build();
Alternatively, you can also load the timeout from configuration. For example, if you add the following to appsettings.json:
{
"HostOptions": {
"ShutdownTimeout": "00:00:15"
}
// other config
}
You can then bind the HostOptions configuration section to the HostOptions object:
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddHostedService<Worker>();
builder.Services.Configure<HostOptions>(
builder.Configuration.GetSection("HostOptions"));