我有一个TopShelf(3.1.3)服务,该服务挂在“停止'提出异常时的状态。因此,不会调用任何服务恢复步骤,并且只有通过“任务杀死”手动终止服务才能成功卸载服务。
在TopShelf中处理异常的推荐方法是什么?我不希望简单地吞下/记录异常并继续。理想情况下,对hostControl.Stop的调用确实会使服务停止在'停止'但是情况并非如此。
这个帖子提出了一个类似的问题,但它没有提供答案: How to catch exception and stop Topshelf service?
思想?
HostFactory.Run(o =>
{
o.UseNLog();
o.Service<TaskRunner>();
o.RunAsLocalSystem();
o.SetServiceName("MyService");
o.SetDisplayName("MyService");
o.SetDescription("MyService");
o.EnableServiceRecovery(r => r.RunProgram(1, "notepad.exe"));
});
public class TaskRunner : ServiceControl
{
private CancellationTokenSource cancellationTokenSource;
private Task mainTask;
public bool Start(HostControl hostControl)
{
var cancellationToken = cancellationTokenSource.Token;
this.mainTask = Task.Factory.StartNew(() =>
{
try
{
while (!this.cancellationTokenSource.IsCancellationRequested)
{
// ... service logic ...
throw new Exception("oops!");
}
}
catch (Exception)
{
hostControl.Stop();
}
});
return true;
}
public bool Stop(HostControl control)
{
this.cancellationTokenSource.Cancel();
this.mainTask.Wait();
return true;
}
}
答案 0 :(得分:1)
看起来topshelf捕获异常并试图很好地关闭,这意味着你可以通过关闭获得循环逻辑。例如,你有一个引发异常的线程,topshelf捕获它并要求所有stopables停止。其中一个是启动违规线程的服务,因此它调用thread.join();这意味着它正在等待自己完成所以它可以完成。我认为这就是你的task.wait()。
所以,解决方案真的归结为:
我最终会有超时,及时结束服务,并允许我的异常日志记录运行。
答案 1 :(得分:0)
尝试在try catch块外部移动while循环
public bool Start(HostControl hostControl)
{
var cancellationToken = cancellationTokenSource.Token;
this.mainTask = Task.Factory.StartNew(() =>
{
while (!this.cancellationTokenSource.IsCancellationRequested)
{
try
{
// ... service logic ...
throw new Exception("oops!");
}
catch (Exception)
{
hostControl.Stop();
}
}
});
return true;
}