所以我有一个看起来像这样的后台服务。
public class MyBackgroundService: BackgroundService
{
public MyBackgroundService(){}
protected override Task ExecuteAsync(CancellationToken stoppingToken)
{
new Thread(() => new MessageHandler().Process(stoppingToken).Start();
return Task.CompletedTask;
}
}
如果 Process-method 抛出异常,是否可以尝试重新启动 后台服务或创建一个新的 MessageHandler 并运行 Process?
编辑,经过反馈和谷歌搜索,我在想这样的事情
protected override Task ExecuteAsync(CancellationToken cancellationToken)
{
Task.Run(() => RunConsumer(cancellationToken)).Start();
return Task.CompletedTask;
}
private void RunConsumer(CancellationToken cancellationToken)
{
while (true)
{
using var scope = _serviceScopeFactory.CreateScope();
var myConsumer = scope.ServiceProvider.GetRequiredService<IMyConsumer>();
Task.Run(() => { new Thread(() => myConsumer.Start()).Start(); })
.ContinueWith(t =>
{
if (t.IsFaulted) {/* Log t.Exception and retry x times */}
if (t.IsCompleted) {/* Should not not happen in my case */}
});
}
}
你可以这样编写主循环:
protected override Task ExecuteAsync(CancellationToken cancellationToken)
{
while(!cancellationToken.IsCancellationRequested)
{
try {
await RunConsumer(cancellationToken);
}
catch (Exception e)
{
// log exception
}
await Task.Delay(TimeSpan.FromSeconds(30)); // To prevent restarting too often
}
return Task.CompletedTask;
}
重点是
cancellationToken.IsCancellationRequested
,服务将在请求时停止,例如当这个过程优雅地结束时,Task.Delay
确保进程不会过于频繁地重新启动。在
RunConsumer
中你可以使用
await Task.Run(() => new MessageHandler().Process(stoppingToken).Start());
通常最好使用 async/await,这样你就不必手动进行延续和错误检查。