任务未处理的exception

我试图了解在任务对象中抛出但从未处理过的exception发生了什么。

在MSDn上,据说:

如果您不等待传播exception的任务或访问其Exception属性,则在对任务进行垃圾回收时,将根据.NETexception策略升级exception。

所以我不太明白这些exception会以何种方式影响程序流程。 我认为这些exception应该在垃圾收集后立即中断执行。 但我无法设计这种行为。 在以下代码段中,抛出的exception不会显示。

\\Do something ... Task.Run (()=> {throw new Exception("Exception in the task!");}); \\Do something else 

请问,任何人都可以解释如何处理未处理的任务exception,以及它们如何影响程序流程。

您正在描述.NET 4中的行为,但是您很难强制执行垃圾收集并实际观察该行为。 以下引自斯蒂芬·图布(Stephen Toub)关于这一主题的优秀文章,应该更清楚:

任务跟踪是否“观察到未处理的exception”。在此上下文中,“观察”意味着代码以某种方式与Task连接,以便至少知道exception。 这可能是在Task上调用Wait / WaitAll。 任务完成后,可以检查Task的Exception属性。 或者它可能正在使用Task的Result属性。 如果一个任务看到以某种方式观察到它的exception,那么生活是美好的。 但是,如果删除了对Task的所有引用(使Task可用于垃圾收集),并且如果尚未观察到它的exception,则Task知道永远不会观察到它的exception。 在这种情况下,Task利用finalization,并使用辅助对象在终结器线程上传播未处理的exception。 使用前面描述的行为,终结器线程上的该exception将被取消处理并调用默认的未处理exception逻辑,即记录问题并使进程崩溃。

他还提出了两个有用的扩展方法来处理“即发即弃”任务中的exception:一个忽略exception,另一个立即崩溃进程:

 public static Task IgnoreExceptions(this Task task) { task.ContinueWith(c => { var ignored = c.Exception; }, TaskContinuationOptions.OnlyOnFaulted | TaskContinuationOptions.ExecuteSynchronously | TaskContinuationOptions.DetachedFromParent); return task; } public static Task FailFastOnException(this Task task) { task.ContinueWith(c => Environment.FailFast(“Task faulted”, c.Exception), TaskContinuationOptions.OnlyOnFaulted | TaskContinuationOptions.ExecuteSynchronously | TaskContinuationOptions.DetachedFromParent); return task; } 

在.NET 4.5中 ,默认行为已更改。 再一次,引自另一位Stephen Toub关于这个主题的post (感谢mike z在评论中引起我的注意):

为了使开发人员更容易根据Tasks编写异步代码,.NET 4.5更改了未观察到的exception的默认exception行为。 虽然未观察到的exception仍会导致引发UnobservedTaskException事件(不会这样做会发生重大变化),但默认情况下进程不会崩溃。 相反,无论事件处理程序是否观察到exception,exception将在事件引发后最终被吃掉。 但是,可以配置此行为。