为什么我的程序终止时,任务有未处理的异常? [英] Why doesn't my process terminate when Task has unhandled exception?

查看:120
本文介绍了为什么我的程序终止时,任务有未处理的异常?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我建立一个Windows服务在.NET 4.0。

I am building a Windows Service with .NET 4.0.

我扔在不同的任务未处理的异常,但他们没有终止我的过程,因为MSDN文档状态(的并行任务 - 看不可观测任务例外)

I have various unhandled exceptions thrown in Tasks, but they do not terminate my process as the MSDN documentation states (Parallel Tasks - see Unobserved Task Exceptions).

如果你不给故障任务的机会,传播其   异常(例如,通过调用Wait方法),所述运行时将   根据当前的升级任务的不可观测的例外   当任务是垃圾回收.NET异常策略。

"If you don't give a faulted task the opportunity to propagate its exceptions (for example, by calling the Wait method), the runtime will escalate the task's unobserved exceptions according to the current .NET exception policy when the task is garbage-collected."

它的行为是这样,甚至当我使用任务的最简单的invokation:

It behaves like this even when I use the most simple invokation of a task:

Task.Factory.StartNew(() => { throw new Exception(); } 

该服务不断运行良好时调用。

The service keeps on running fine when that is called.

根据文档,任务的终结将重新抛出异常一旦任务GC'd但是这似乎并没有发生。 MSDN多次指出,在进程终止正常的.NET异常策略的结果。

According to the docs, the finalizer of the Task will rethrow the exception once the Task is GC'd but this does not appear to happen. MSDN states repeatedly that normal ".NET exception policy" results in process termination.

为什么不这样结束我的应用程序?我唯一​​能想到的是有莫名其妙的引用某处举行的任务(是拉姆达?)

Why doesn't this terminate my app? The only thing I can think is there is somehow a reference to the task held somewhere (is it the lambda??)

推荐答案

所建议的@Hans和@ codeInChaos我发现重新抛出的未处理的异常(从而杀死进程)的唯一方法是强制终结到运行(注意:确保你不这样做,在 ContinueWith()!):

As suggested by @Hans and @CodeInChaos I found the only way to rethrow the unhandled exception (thus killing the process) is to force the Finalizer to run (Note: Make sure you dont do this in the ContinueWith()!):

GC.Collect(); 
GC.WaitForPendingFinalizers();

在我的特殊情况下的任务不是垃圾回收,因为程序的流程取决于任务是成功的。如果没有流量继续我的应用程序不会做任何造成GC(分配对象等)。

In my particular circumstances the Task was not garbage collected because the flow of the program depended on the Task being succesful. Without the flow continuing my app would not do anything to cause a GC (allocate objects etc).

有趣的是,即使做了 GC.Collect的()是远远不够的。任务终结还是没有运行。该 GC.WaitForPendingFinalizers()必须显式调用。 (我怀疑我不明白周围定稿微妙之处)。

What is interesting is that even doing a GC.Collect() is not enough. The Task finalizer still did not run. The GC.WaitForPendingFinalizers() had to be called explicitly. (I suspect I do not understand subtleties around Finalization).

要总结:不要指望一个第三方物流任务的未观察到的异常的行为类似于其它线程机制的未处理的异常的行为(例如 QueueUserWorkItem )。在最实际的情况下,你需要显式检查的任务例外:你可以不依赖于不可观测的例外是引起您注意的方式,他们将与QUWI或相似的,因为你只会看到他们的终结抛出这完全取消predictable。

To summarize: Dont expect a TPL Task's unobserved exception behaviour to be similar to other threading mechanisms unhandled exception behaviour (e.g. QueueUserWorkItem). In most practical situations you need to explicity check for Exceptions from Tasks: you cannot rely on unobserved exceptions being brought to your attention in the way they would with a QUWI or similar because you will only see them thrown from the Finalizer which is totally unpredictable.

编辑:看我其他有关的答案.NET 4.5

See my other answer concerning .NET 4.5

这篇关于为什么我的程序终止时,任务有未处理的异常?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆