目標:
在 Windows 上運行 .net 6.0 BackgroundService,當發生未處理的例外時會自動重新啟動。
最小的例子:
程式.cs
IHost host = Host.CreateDefaultBuilder(args)
.ConfigureServices(services =>
{
services.AddHostedService<Worker>();
})
.UseWindowsService(options =>
{
options.ServiceName = "ASampleService";
})
.Build();
await host.RunAsync();
工人.cs
namespace SampleWindowsService
{
public class Worker : BackgroundService
{
[...]
protected override async Task ExecuteAsync(CancellationToken stoppingToken)
{
while (!stoppingToken.IsCancellationRequested)
{
await Task.Delay(TimeSpan.FromSeconds(10), stoppingToken);
throw new Exception();
}
}
}
}
sc失敗配置
sc failure ASampleService reset=0 actions= restart/5000
預期行為
該服務應在啟動后 10 秒崩潰,然后在崩潰后 5 秒重新啟動。它應該無限期地這樣做。系統事件日志應包含一條日志行,說明 ASampleService 崩潰并將由服務控制管理器在 5000 毫秒內重新啟動。
實際行為
服務崩潰并在應用程式事件日志中生成一條日志行“服務已成功停止”,并且永遠不會重新啟動。
問題
我猜“成功停止”的日志是問題的核心。根據這篇文章:
“當服務終止而不向服務控制器報告 SERVICE_STOPPED 狀態時,服務被視為失敗。”
但是,我還沒有找到阻止服務“成功停止”的方法,即使重寫 BackgroundService 的 StopAsync 函式或 IHostApplicationLifecycle 的 OnStop 并在那里拋出例外,也沒有阻止這條日志行。
我一直在深入研究源代碼以了解正在發生的事情,并且我開始認為我可能需要使用較低級別的抽象來使其正常作業。但是,如果這里有人知道如何使它起作用,我最有興趣了解您的方法。
uj5u.com熱心網友回復:
protected override async Task ExecuteAsync(CancellationToken stoppingToken)
{
try
{
while (!stoppingToken.IsCancellationRequested)
{
// simulate some work here
await Task.Delay(TimeSpan.FromSeconds(5));
// something went wrong
throw new Exception();
}
}
catch
{
// prevent "Stopped successfully"
Environment.Exit(1);
}
}
.net 檔案中的文章也將更新。您可能還希望將退出代碼設定為例外的 HResult。
使用此代碼,scm 將重新啟動服務,系統日志將顯示正確訊息:
SampleService 服務意外終止。它已經這樣做了 1 次。將在 5000 毫秒內采取以下糾正措施: 重新啟動服務。
轉載請註明出處,本文鏈接:https://www.uj5u.com/net/470008.html