【发布时间】:2020-07-08 20:35:54
【问题描述】:
我有一个默认的通用主机构建器,如下所示:
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();
}
我正在使用UseConsoleLifetime 和 docker 运行应用程序,它运行,但我似乎无法正常关闭。
我通过 PowerShell 中的 docker stop 命令优雅地向我的应用程序发送停止信号。
但是,与我按 control+C 的控制台应用不同,该应用没有收到此停止命令,并且在 10 秒后被强制终止。
我的问题是:
- 如何检测 docker shutdown 命令?
- 如何根据我调用的方法注册两种关闭方法(通过控制台或 docker)(有时我可以直接在 Visual Studio 中作为控制台进行调试,而大多数情况下我会通过 docker 使用,但会很高兴为这两种情况自动注册)。
编辑和更新
我看到回复了,谢谢,提坑AppDomain.CurrentDomain.ProcessExit。
对于我的工作人员BackgroundService,该接口具有以下功能:
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);
}
}
}
每当发送 ctrl+c 时使用UseConsoleLifetime,设置停止令牌。
在docker内使用相同代码(包括UseConsoleLifetime与原代码相同)时,未设置stoppingToken。
请注意,我看不到我有权访问此令牌源以执行取消。
如果我注册到AppDomain.CurrentDomain.ProcessExit,我如何使用它来设置stoppingToken(而不是制作我自己的stopping token 源,虽然可以做到,但如果可能的话想避免)。
【问题讨论】:
-
你试过this吗?
-
看起来不错,谢谢,
Domain.CurrentDomain.ProcessExit可以与UseConsoleLifetime()并行运行,或者以任何特定方式检测是作为控制台运行还是通过 docker 运行以说明任一注册? -
不确定,但您也可以尝试订阅
System.Console.CancelKeyPress活动。 -
您无需注册
ProcessExit或任何其他活动。UseConsoleLifetime()监听 Ctrl+C、SIGINT 和 SIGTERM - 它已经监视进程终止。当你运行docker stop时,SIGTERM 被发送到容器的根进程。这是你的申请还是其他申请?您如何构建和运行主机?.Build().RunAsync()?还有什么? -
您的 BackgroundService 代码是什么样的?当发出终止信号时,会发出通过
ExecuteAsync的CancellationToken信号。你的代码应该监控它并在它被引发时迅速退出