任务异常管理c#

时间:2015-01-12 12:18:13

标签: c# .net exception-handling async-await task-parallel-library

我运行的解决方案包含2个项目:app和sdk。

通过应用程序,我创建了一个sdk实例,以便应用程序可以启动。问题是,当我在Task内部运行的代码中遇到异常时,不会抛出Unhandled Exception,因此我的应用程序一直在运行,并且没有意识到SDK中发生了意外情况。

我已在App和SDK中注册了AppDomain.CurrentDomain.UnhandledException的事件,但正如在任务中抛出异常时所述,事件处理程序未被调用。

我有什么遗失的东西吗?

3 个答案:

答案 0 :(得分:5)

这两个答案都有些(但并非完全)完整。

异步

处理故障任务的最佳方法是异步等待,以便使用await完成。这将重新抛出原始存储的异常:

try
{
    await task;
}
catch (Exception e)
{
    // handle exception
}

同步

如果你不能这样做(或者不想),你也可以使用task.Wait()同步等待并抛出包含原始异常的 AggregateException < / strong>在InnerExceptions中或注册处理它的延续(即task.ContinueWith(t => // handle exception)

UnobservedTaskException

在.Net 4.0中,未观察到的任务异常会导致整个过程失效。 TaskScheduler.UnobservedTaskException事件是崩溃前处理异常的最后一个选项(非常类似于UnhandledException的情况)。在.Net 4.5中,这种类型的异常不再使应用程序崩溃,但事件仍然被提升

如果你想在这种情况下崩溃应用程序(我怀疑你这样做),你可以设置<ThrowUnobservedTaskExceptions enabled="true"/>,因为Yuval指出。您可以使用事件本身来处理因两个原因而不是最佳的异常:

  1. .Net决定您的任务的异常仅在任务被垃圾收集时才会被观察到可能随时发生(或者,如果您不发布对它的所有引用,则永远不会) 。在此之前,你可能仍然自己处理异常,所以它还没有被观察到。
  2. 你得到了例外,但没有得到任务,没有它就很难知道问题的真正根源。
  3. 结论

    确保await您的任务在发生异常时处理。如果您错过任务,也可以使用UnobservedTaskException作为捕获。

答案 1 :(得分:3)

Task抛出未处理的异常时,其执行将终止,您可以检查原始IsFaulted对象上的ExceptionTask属性。

有关这些属性的更多信息herehere,还有一篇专门讨论任务on the MSDN中的异常处理的文章

UnobservedTaskException上还有TaskScheduler个活动。我自己从未使用它,但阅读它,它应该与UnhandledException上的AppDomain事件类似。检查on MSDN

答案 2 :(得分:3)

  

问题是当我在代码运行的一部分中得到异常时   在任务内部,没有抛出未处理的异常,所以我的应用程序保持不变   运行并没有意识到SDK中发生了意外情况。

这不完全正确(感谢@ l3arnon进行更正):Task将在.NET 4.0和.NET 4.5中传播异常,并将触发UnobservedTaskException。两者之间的区别在于,.NET 4.5将在其触发后悄悄地吞下异常,而不是.NET 4.0,如果该事件未处理,将导致进程崩溃。

您可以通过&quot; app.config and ThrowUnobservedTaskExceptions更改回.NET 4.0行为                                             

还有其他几种方法可以解决这个问题:

  1. 在您的代码中使用await Task.Runawait将从任务内部解开您的异常。
  2. 如果您不想等待并想要使用&#34; Fire and Forget&#34;方法,你可以附上一个延续:

    Task.Run(() => {}).ContinueWith(task => { */ Handle Exceptions here */ },
                                    TaskContinutationOptions.OnlyOnFaulted);