我正在使用.NET Core 3.1工作程序服务模板来构建Windows服务。
我认为基本流程应在ExecuteAsync
中处理,大致如下:
protected override async Task ExecuteAsync(CancellationToken stoppingToken)
{
while (!stoppingToken.IsCancellationRequested)
{
try
{
_Logger.LogInformation("Worker running at: {time}", DateTimeOffset.Now);
await SomeMethodThatDoesTheWork(stoppingToken);
}
catch (Exception ex)
{
_Logger.LogError(ex, "Global exception occurred. Will resume in a moment.");
}
await Task.Delay(TimeSpan.FromSeconds(10), stoppingToken);
}
}
我正在尝试从进程中正确发出信号,要求我关闭应用程序。
停止服务时,我假设调用StopAsync()
。这似乎很好。因此,我认为await StopAsync()
可以解决问题,但是之后,ExecuteAsync
仍然保持运行状态(因此,我猜测StopAsync
不会要求取消,因此您不应该调用它你自己)。
所以我用另一个布尔值修改了循环:
while (!stoppingToken.IsCancellationRequested && !_ShuttingDown)
这确实会退出循环,并且永远不会再输入ExecuteAsync
。但是,该应用程序仍在继续运行。根据调试器,它只是停留在host.Run()
上。
如何向要关闭的应用程序主机发信号?
答案 0 :(得分:2)
在ASP.NET Core中,后台服务独立于应用程序。例如,服务可能会完成,而应用程序仍会继续执行。如果您希望在后台服务完成时退出应用程序,则需要自行进行连接。
您可以向服务中注入IHostApplicationLifetime
,然后致电IHostApplicationLifetime.StopApplication
。像这样:
public sealed class MyService : BackgroundService
{
private readonly IHostApplicationLifetime _hostApplicationLifetime;
private readonly ILogger<MyService> _logger;
public MyService(IHostApplicationLifetime hostApplicationLifetime, ILogger<MyService> logger)
{
_hostApplicationLifetime = hostApplicationLifetime;
_logger = logger;
}
protected override Task ExecuteAsync(CancellationToken stoppingToken)
{
try
{
while (!stoppingToken.IsCancellationRequested)
{
try
{
_logger.LogInformation("Worker running at: {time}", DateTimeOffset.Now);
await SomeMethodThatDoesTheWork(stoppingToken);
}
catch (Exception ex)
{
_logger.LogError(ex, "Global exception occurred. Will resume in a moment.");
}
await Task.Delay(TimeSpan.FromSeconds(10), stoppingToken);
}
}
finally
{
_logger.LogCritical("Exiting application...");
_hostApplicationLifetime.StopApplication();
}
}
}
答案 1 :(得分:0)
服务不应该停止自身,它们不是应用程序-它们是服务...
为什么要从服务内部停止服务?也许您想要预定的任务而不是服务。
您始终可以使用ServiceController或类似的类将stop事件发送到服务