I have a default generic host builder as below:
public static IHostBuilder CreateDefaultBuilder(string[] args)
{
var builder = Host.CreateDefaultBuilder(args);
builder
.ConfigureLogging((hostingContext, logging) =>
{
logging.ClearProviders();
logging.AddConsole();
if (hostingContext.HostingEnvironment.IsDevelopment() == true)
logging.AddDebug();
})
.ConfigureHostConfiguration(configurationBuilder =>
{
configurationBuilder.AddCommandLine(args);
})
.ConfigureAppConfiguration((hostingContext, configApp) =>
{
var env = hostingContext.HostingEnvironment;
Console.WriteLine(env.EnvironmentName);
})
.UseConsoleLifetime();
return builder;
}
public static async Task Main(string[] args)
{
var host = CreateDefaultBuilder(args)
.ConfigureServices((hostContext, services) =>
{
services.Configure<HostOptions>(option =>
{
option.ShutdownTimeout = System.TimeSpan.FromSeconds(20);
});
services.AddLogging();
services.AddSimpleInjector(container, options =>
{
// Hooks hosted services into the Generic Host pipeline while resolving them through Simple Injector
options.AddHostedService<Worker>();
// Allows injection of ILogger & IStringLocalizer dependencies into application components
options.AddLogging();
// options.AddLocalization();
});
})
.Build()
.UseSimpleInjector(container);
config.Build();
await host.RunAsync();
}
I am using UseConsoleLifetime
and docker to run the application, it runs, but i do not seem to be able to gracefully shutdown.
I gracefully send a stop signal to my application via the docker stop
command in PowerShell.
However, unlike my console app where i press control+C, the app doesn't get this stop command and after 10 seconds is killed forcibly.
My questions are please:
- How can i detect the docker shutdown command?
- How can i register both methods of shutdown (via console or docker) depending on the method by which i am calling (at times I may debug directly in Visual Studio as a console, whereas mostly i would use via docker, but would be nice to auto-register for both scenarios).
EDIT AND UPDATE
I have seen replies, thank you, mentioning to trap on AppDomain.CurrentDomain.ProcessExit
.
For my worker BackgroundService
the interface is such that it has the function:
public class Worker : BackgroundService
{
protected override async Task ExecuteAsync(CancellationToken stoppingToken)
{
while (!stoppingToken.IsCancellationRequested)
{
logger.LogInformation("running at: {time} - stoppingToken {stoppingToken}", DateTimeOffset.Now, stoppingToken.IsCancellationRequested);
await Task.Delay(1000, stoppingToken);
}
}
}
Using the UseConsoleLifetime
whenever ctrl+c is sent, the stoppingToken is set.
When using the same code (including UseConsoleLifetime
same code as is) within docker, the stoppingToken is not set.
Note i cant see that i have access to this token source in order to perform the cancellation.
If i register to AppDomain.CurrentDomain.ProcessExit
how can i use this to set the stoppingToken (as opposed to making my own stopping token source, as whilst can be done, would like to avoid if possible).