任务应该如何正确地发出Windows服务关闭的信号



我正在处理一个Windows服务的错误。该服务使用一个字段来跟踪对单个Task的引用。在启动时,任务执行单个方法。该方法内部有一个循环,并以可配置的间隔调用数据库,以监视另一个系统正在执行的工作。

protected override void OnStart(string[] args)
{
_processorTask = Task.Run(() => StartProcessor());
}

我们偶尔会遇到这样的问题,Task会终止并记录异常,但现有的管道并没有告诉服务停止,所以我们的服务监视器不知道有什么问题。

起初,我尝试添加一个对Stop((的调用。

private void StartProcessor()
{
var processor = new PEMonitoringProcessor(_tokenSource.Token);

try
{
// The process loop is in the function. If this method exits, good or bad, the service should stop.
processor.ProcessRun();
}
catch (Exception ex)
{
// An exception caught here is most likely fatal. Log the ex and start the service shutdown.
if (log.IsFatalEnabled) { log.Fatal("A fatal error has occurred.", ex); };
}
finally
{
Stop();
}
}

然而,我的一位开发伙伴在OnStop方法中注意到,使用一个令牌来通知Task停止,然后等待。如果Task调用Stop并等待Stop返回,而OnStop正在等待Task结束,那么这对代码来说不是好兆头。

protected override void OnStop()
{
_tokenSource.Cancel();
try
{
_processorTask.Wait();
}
// logging & clean-up... 
}

我考虑了一个单独的Task,它不会被OnStop等待,它会检查第一个Task的状态,并在第一个Task完成、出错等时调用Stop,但这似乎有点奇怪。我还考虑过引发一个事件并尝试类似BeginInvoke的方法。

有意停止服务运行良好,因为OnStop通过Token发出关闭信号。我试图掩盖Task方法意外返回或抛出的可能性,我希望服务停止,而不是变成僵尸。

我看到的最直接的方法是这样的:

protected override void OnStart(string[] args) {
_processorTask = Task.Run(() => StartProcessor());
_processorTask.ContinueWith(x => {
// x.Exception contains exception if any, maybe log it here
Stop();
}, TaskContinuationOptions.NotOnCanceled);
}
protected override void OnStop() {
//or !_processorTask.IsCompleted && !_processorTask.IsCanceled && !_processorTask.IsFaulted
if (_processorTask.Status == TaskStatus.Running) {
// only cancel and wait if still running. Won't be the case if service is stopping from ContinueWith above
_tokenSource.Cancel();
_processorTask.Wait(); 
}
}

另一种方法:

protected override async void OnStart(string[] args) {
_processorTask = Task.Run(() => StartProcessor());
bool cancelled = false;
try {
await _processorTask;
}
catch (OperationCanceledException) {
// cancelled
cancelled = true;
}
catch (Exception ex) {
// log it?
}
if (!cancelled)
Stop();
}
// OnStop stays the same

相关内容

  • 没有找到相关文章

最新更新