【发布时间】:2016-09-21 04:40:45
【问题描述】:
我正在开发一个 Windows 服务应用程序,它使用 TPL 来启动它的主要处理任务。
处理任务是一个连续的 while 循环,一旦启动,它就会继续执行,直到发出来自 Windows 服务基础架构的取消请求。
启动实现如下:
protected override void OnStart(string[] args)
{
continuousProcessingTask = Task.Factory.StartNew(
() => DoStuffInAWhileLoopUntilCancelled(cancellation), cancellation,
TaskCreationOptions.LongRunning, TaskScheduler.Default);
}
问题是,如果主任务中的某处(在 DoStuffInAWhileLoopUntilCancelled 方法中)发生未经处理的异常,我希望终止服务。
更准确地说,我希望在处理任务中发生未处理的异常时服务处于一致状态。使用上面的 sn -p 最终会出现正在运行的 windows 服务但处理任务终止的情况,在我看来这是不一致的。 在我的理解中,一致的行为意味着处理任务/线程和父服务进程都在运行,或者什么都没有运行。
我最终采用了延续方法,如果主处理线程失败则关闭服务进程:
protected override void OnStart(string[] args)
{
continuousProcessingTask = Task.Factory.StartNew(
() => DoStuffInAWhileLoopUntilCancelled(cancellation), cancellation,
TaskCreationOptions.LongRunning, TaskScheduler.Default)
.ContinueWith(OnTaskCompleted);
}
void OnTaskCompleted(Task task)
{
if (task.IsFaulted)
{
if (task.Exception != null)
{
Service.EventLog.SafeWriteEntry(task.Exception.ToString(), EventLogEntryType.Error);
}
// shut down the application
System.Environment.Exit(-1);
}
}
但我不确定这是否是这里推荐的方法 - System.Environment.Exit 看起来很丑(并且打破了类隔离)。是否有其他选项可用于处理此模式中的主处理任务的终止(第一个代码 sn-p)?
UPD1: 澄清了上面的问题。
【问题讨论】:
-
如果这种情况发生在服务本身,为什么不直接在服务上调用 Stop 呢? msdn.microsoft.com/en-us/library/…
-
这个应用程序可以作为控制台进程(对于开发人员)和作为服务(对于产品)运行。这是个好主意,谢谢,我可以尝试在 System.Environment.Exit 上调用 Stop。但是现在我明白我的问题稍微宽泛了——我一般应该如何在主要处理任务中处理未经处理的异常......?
-
当你在控制台应用程序中运行时——只要让它像往常一样退出主方法。除非绝对必要,否则不要使用 Environment.Exit(或 FailFast 等)。如果您遇到未处理的异常 - 您的应用程序应该记录、清理并正常退出。如果这是一项始终在运行的服务 - 将其配置为自动重启。
-
谢谢。基本上,这就是我对这些服务所拥有的——它们根据服务恢复操作无限期地重新启动。看起来,我现在拥有的(第二个代码 sn-p)几乎就是它,除了优雅退出(只需要替换 System.Environment.Exit)。 raidensan 的论点是服务应该连续运行,所以我想知道是否应该在已经运行的服务进程中完成处理任务重启......(这可以被检测到并继续完成)
-
一种选择是重新抛出异常,这将导致进程异常终止。这样做的潜在优势是它应该触发 Windows 服务故障处理,允许您将服务配置为在故障时自动重新启动。
标签: c# multithreading exception-handling windows-services task-parallel-library