我正在阅读互动扩展程序的源代码,并发现了一个我不明白的
line:
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; }
我也没有在文档中看到有关IsFaulted或Exception属性的任何相关的备注.
为什么这行var ignored = t.Exception; //不要删除!在这种情况下是需要的吗?
一个相关的问题:我认为这样的行在发布模式下被优化了,但是在这里给出了评论和意图,情况并非如此(如果代码是正确的).那么为什么这条线保持在Release模式?
解决方法
该行是观察到的异常和不可观察的异常之间的差异.
在.Net 4.0中,具有未查看异常的任务将抛出UnobservedTaskException并将整个应用程序拆下:
“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.”
从Exception Handling (Task Parallel Library)
虽然可以使用app.config(< ThrowUnobservedTaskExceptions enabled =“true”/>)来恢复旧的行为,但在.Net 4.5中已经改为async-await.
还有一个事件(TaskScheduler.UnobservedTaskException),允许您在应用程序崩溃之前处理此类故障任务.这个事件在.Net 4.5及以上仍在提高.