任务未处理的异常 [英] Task unhandled exceptions

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

问题描述

我想明白是怎么回事,与抛出一个任务对象,永远处理的异常

I'm trying to understand what is going on with exceptions that are thrown within a task object and never handled.

在MSDN有人说:

如果你不上传播异常,或b其异常属性访问$ b $任务等待,异常是根据升级当任务是垃圾回收
.NET异常策略。

If you do not wait on a task that propagates an exception, or access its Exception property, the exception is escalated according to the .NET exception policy when the task is garbage-collected.

所以,我不太明白什么方式的异常影响程序流程。我认为,这些异常应该尽快,因为它们是垃圾收集中断执行。但我不能设计此行为。在下面的代码片段抛出的异常不出来。

So I don't quite understand in what way those exceptions affect program flow. I thought that those exceptions should interrupt execution as soon as they are garbage-collected. But I can not design this behaviour. Within the following snippet the thrown exception doesn't show up.

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

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

Please, can anyone explain how unhandled task exception are dealt with, and how they affect program flow.

推荐答案

您所描述的行为,因为它的在.NET中4 ,但它将是你很难强迫垃圾收集和实际观察到的行为。从斯蒂芬Toub的外观极好写了下面的报价的关于这个问题应该使其更加明确:观察

You're describing the behavior as it was in .NET 4, but it will be difficult for you to force the garbage collection and actually observe that behavior. The following quote from Stephen Toub's excelent write-up on the subject should make it even more clear:

任务跟踪未处理的异常是否已经
在这样的背景下, 观察是指代码已经加入了
与工作以某种方式以至少被告知
异常。这可以调用任务等待/为WaitAll。它
可以检查任务的Exception属性任务已经
结束后。或者它可能是使用任务的Result属性。
。如果任务看到它的异常以某种形式被观察到,
生活是美好的。然而,如果给任务的所有引用都被删除
(使得可用于垃圾收集的任务),并且如果其
例外尚未观察到的,任务知道它的异常
将永远不会被观察到。在这种情况下,任务利用
定稿,并使用一个辅助对象传播终结线程上未处理
例外。随着行为描述
早些时候,终结线程上的异常会未处理和
调用默认未处理的异常逻辑,这是记录
问题和崩溃的过程。

Tasks keep track of whether an unhandled exception has been "observed." In this context, "observed" means that code has joined with the Task in some fashion in order to at least be made aware of the exception. This could be calling Wait/WaitAll on the Task. It could be checking the Task’s Exception property after the Task has completed. Or it could be using a Task’s Result property. If a Task sees that its exception has been observed in some manner, life is good. If, however, all references to a Task are removed (making the Task available for garbage collection), and if its exception hasn’t yet been observed, the Task knows that its exception will never be observed. In such a case, the Task takes advantage of finalization, and uses a helper object to propagate the unhandled exception on the finalizer thread. With the behavior described earlier, that exception on the finalizer thread will go unhandled and invoke the default unhandled exception logic, which is to log the issue and crash the process.

他还建议两个有用的扩展方法在发射后不管的任务异常处理:一是忽略了例外,另一个立即崩溃过程:

He also suggested two useful extension methods for handling exceptions in "fire-and-forget" tasks: one ignoring the exception and the other one immediately crashing the process:

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 的默认行为已更改。再次,从另一斯蒂芬Toub的关于这个问题的后(感谢迈克z代表它带给我的注意力在评论):

In .NET 4.5 the default behavior has changed. Again, a quote from another Stephen Toub's post on the subject (thanks to mike z for bringing it to my attention in the comments):

为了让开发者更容易根据$ b编写异步代码$ b任务,.NET 4.5的变化未观测到的
异常的默认异常行为。虽然没有观察到异常仍然将导致提出的
UnobservedTaskException事件(不这样做将是
重大更改),这个过程不会在默认情况下崩溃。相反,
的异常最终将引发该事件,
不管事件处理程序是否观察异常后得到吃掉。此
行为可以被配置,虽然

To make it easier for developers to write asynchronous code based on Tasks, .NET 4.5 changes the default exception behavior for unobserved exceptions. While unobserved exceptions will still cause the UnobservedTaskException event to be raised (not doing so would be a breaking change), the process will not crash by default. Rather, the exception will end up getting eaten after the event is raised, regardless of whether an event handler observes the exception. This behavior can be configured, though.

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

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