简体   繁体   English

Tpl的延续和例外?

[英]Tpl's Continuations and exceptions?

If I have a task which throws an exception , I can check in the continuation if there was an exception: 如果我有一个引发异常的任务,则可以在延续中检查是否存在异常:

Task task1 = Task.Factory.StartNew (() => { throw null; });
Task task2 = task1.ContinueWith (ant => Console.Write (ant.Exception));

But I also know that : 但我也知道:

If an antecedent throws and the continuation fails to query the antecedent's Exception property (and the antecedent isn't otherwise waited upon), the exception is considered unhandled and the application dies . 如果一个前件引发并且延续无法查询该前件的Exception属性(并且该前件没有等待),则该异常被视为未处理,并且该应用程序死亡

So I tried : 所以我尝试了:

Task task1 = Task.Factory.StartNew (() => { throw null; });
Task task2 = task1.ContinueWith (ant => Console.Write (1));//1

But the application didn't crash. 但是应用程序没有崩溃。

Please, What am I missing ? 拜托,我想念什么?

There are few different things going on: 发生了几件不同的事情:

First, if you call Wait() on a faulted Task , it will always throw an exception, no matter if you already observed it or not. 首先,如果对有故障的Task调用Wait() ,它将始终引发异常,无论您是否已经观察到它。 In your code, this means that if you call task.Wait() from Main() , the whole application will crash, because you have unhandled exception in Main() . 在您的代码中,这意味着如果您从Main()调用task.Wait() ,则整个应用程序将崩溃,因为Main()有未处理的异常。

Second, the behavior of unhandled exceptions in Task s changed in .Net 4.5 and they will no longer cause the application to crash. 其次, .NET 4.5中Task中未处理的异常的行为已更改 ,它们将不再导致应用程序崩溃。 The article also describes how to switch back to the original behavior. 本文还介绍了如何切换回原始行为。 And if you have .Net 4.5 installed, this applies also to applications targeting .Net 4.0 (eg those built using VS 2010). 如果您安装了.Net 4.5,则这也适用于面向.Net 4.0的应用程序(例如,使用VS 2010构建的应用程序)。

Third, with the .net 4.0 behavior, the application crashes when the Task is garbage collected (assuming the exception wasn't observed before that point). 第三,使用.net 4.0行为, Task被垃圾回收时 ,应用程序崩溃(假定在此之前未观察到异常)。 This is because before that, there is still a chance your code will observe that exception. 这是因为在此之前,您的代码仍有机会观察到该异常。

So, the following code crashes the application (assuming you enabled the .Net 4.0 behavior if you have .Net 4.5 installed): 因此,以下代码使应用程序崩溃(假设您已安装.Net 4.5,则启用了.Net 4.0行为):

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

    // give the Task some time to run
    Thread.Sleep(100);

    GC.Collect();
}

Your code didn't crash, because the GC didn't have chance to run before the application exited normally. 您的代码没有崩溃,因为在应用程序正常退出之前,GC没有机会运行。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM