如何捕获/观察从Task抛出的未处理异常

Bla*_*ski 19 .net c# wpf exception-handling task-parallel-library

我正在尝试在我的应用程序中记录/报告所有未处理的异常(错误报告解决方案).我遇到了一个总是未处理的情景.我想知道如何以未处理的方式捕获此错误.请注意,我今天早上做了很多研究并尝试了很多东西..是的,我已经看过这个,这个以及更多.我只是在寻找一种通用的解决方案来记录未处理的异常.

我在控制台测试应用程序主要方法中有以下代码:

Task.Factory.StartNew(TryExecute);
Run Code Online (Sandbox Code Playgroud)

要么

Task.Run((Action)TryExecute);
Run Code Online (Sandbox Code Playgroud)

以及以下方法:

private static void TryExecute() {
   throw new Exception("I'm never caught");
}
Run Code Online (Sandbox Code Playgroud)

我已经尝试在我的应用程序中连接到以下内容,但它们从未被调用过.

AppDomain.CurrentDomain.UnhandledException
TaskScheduler.UnobservedTaskException
Run Code Online (Sandbox Code Playgroud)

在我最初发现此错误的Wpf应用程序中,我也连接到这些事件,但它从未被调用过.

Dispatcher.UnhandledException
Application.Current.DispatcherUnhandledException
System.Windows.Forms.Application.ThreadException
Run Code Online (Sandbox Code Playgroud)

唯一被称为的处理程序是:

AppDomain.CurrentDomain.FirstChanceException
Run Code Online (Sandbox Code Playgroud)

但这不是一个有效的解决方案,因为我只想报告未捕获的异常(并非每个异常,因为在执行/解析任何catch块之前调用FirstChanceException.

Chr*_*ens 20

如上所述,该TaskScheduler.UnobservedTaskException活动应该能满足您的需求.是什么让你觉得它没有被解雇?

在特定情况下,异常会被任务捕获,然后重新抛出,但不会立即重新抛出.任务的异常会以多种方式重新抛出(在我的脑海中,可能还有更多).

  1. 当您尝试访问结果时(Task.Result)
  2. 调用Wait(),Task.WaitOne(),Task.WaitAll()或其他相关Wait的任务的方法.
  3. 当您尝试在不明确查看或处理异常的情况下处置Task

如果您执行上述任何操作,则会在运行代码的任何线程上重新抛出异常,并且由于您将观察异常,因此不会调用该事件.如果你没有a中的代码try {} catch {},你就会触发AppDomain.CurrentDomain.UnhandledException,这听起来像是可能发生的事情.

重新抛出异常的另一种方式是:

  • 当您不执行上述任何操作时,任务仍然会将异常视为未观察到,并且任务正在完成.它是最后的努力,让你知道有一个你没有看到的例外.

如果是这种情况,并且由于终结器是非确定性的,您是否正在等待GC发生,以便将具有未观察到的异常的那些任务放入终结器队列中,然后再等待它们最终确定?

编辑:这篇文章谈了一点. 本文将讨论事件存在的原因,这可能会让您深入了解如何正确使用事件.