2015-05-15 99 views
10

我读互动扩展的源代码,并发现了一个line,我无法理解:C#任务 - 为什么需要在这种情况下,一个空操作线

public static Task<bool> UsingEnumerator(this Task<bool> task, IDisposable disposable) 
{ 
    task.ContinueWith(t => 
    { 
     if (t.IsFaulted) 
     { 
      var ignored = t.Exception; // don't remove! 
     } 

     if (t.IsFaulted || t.IsCanceled || !t.Result) 
      disposable.Dispose(); 
    }, TaskContinuationOptions.ExecuteSynchronously); 

    return task; 
} 

我还没有看到任何有关言论IsFaultedException属性的文档。

为什么在这种情况下需要此行var ignored = t.Exception; // don't remove!

一个相关的问题:我认为这样的代码行在发布模式下被优化了,但是在这里给出的评论和意图并非如此(如果代码是正确的)。那么为什么这条线保持在发布模式?

+3

在.net 4中,如果任务发生故障但其“Exception”属性未被访问,则任务终结器会引发异常。 – Lee

+0

@李先生谢谢!这实际上写在'Exception'属性的文档中,但是我在第一次阅读时并没有理解它。 –

+1

关于它在发布版本中被删除,'ignored'本地将被删除,但't.Exception'将被解析为它的值(因为它可能,并且在这种情况下确实会导致副作用),那只是在发布版本中将返回值放在地板上,而不是存储在未读变量中。 – Servy

回答

7

该行是观察到的异常和未观察到的异常之间的差异。

在.NET 4.0中与未观测到的异常的任务将抛出UnobservedTaskException和推倒整个应用程序:

“如果你不等待上传播异常的任务,或访问其异常属性,当任务被垃圾收集时,异常会根据.NET异常策略升级。“

Exception Handling (Task Parallel Library)

以.Net 4.5改变与async-await,虽然可以使用回在app.config(<ThrowUnobservedTaskExceptions enabled="true"/>)得到旧的行为。

还有一个事件(TaskScheduler.UnobservedTaskException)允许您在应用程序崩溃之前处理此类故障任务。这个事件仍然在.Net 4.5及以上版本中提出。

+0

@Serv我不同意。它发生了变化,因为“异步等待”被排除在外,从而放弃了以前不常见的任务。 – i3arnon

相关问题