使用 asp.net webapi 和 TPL 捕获未处理的异常
Catching unhandled exceptions with asp.net webapi and TPL
我有一个场景,我创建 Tasks 作为 Webapi 调用的一部分。当任务中发生异常时,它不会被捕获,我不知道如何为此实现全局异常处理程序。
特别是:
- This question and the solution for Web API Global Error Handling 不适用于任务。我猜是因为这些是在 webapi 不知道的线程上执行的。
- 正在订阅 AppDomain.UnhandledException Event does not work either。可能是因为虚拟主机捕获所有未处理的异常并且不让它们冒泡。
如果您认为上述任何方法都有效,请告诉我,我会提出一个我观察到的可重现的小例子。否则,这样做的正确方法是什么?
[HttpGet]
public IQueryable<Thingies> Thingies()
{
Task.Run(() => { throw new ApplicationException("How do I catch all of these globally?"); });
return _db.Thingies;
}
我还要注意,该应用程序不依赖于 System.Web
,我不想介绍它们。
使用async-await而不是直接使用Task,异常处理会很简单如下:
try
{
// Asynchronous implementation.
await Task.Delay(1000);
}
catch (Exception ex)
{
// Handle exceptions.
}
或者,如果您仍然需要使用任务,则按照此处所述继续使用:How to manage properly an exception in a Task with ContinueWith
从 运行 任务内部抛出的异常不会得到处理。他们在那个任务上被捕获,导致它出错。
处理这些异常的正确方法是等待每个任务,或使用 Task.ContinueWith
注册延续。但是,如果您想要一个全局处理程序,您可以使用 TaskScheduler.UnobservedTaskException
事件。
当任务中出现异常时,它会被处理并存储在 Task
对象中供您观察。如果任务被垃圾收集并且异常还没有被任何代码观察到,.Net 知道它永远不会被观察到(因为你没有对任务的引用)并引发 TaskScheduler.UnobservedTaskException
事件(在.Net 4.0 它也会使应用程序崩溃,并且这种行为也可以在较新的版本中复制。
因此,TaskScheduler.UnobservedTaskException
的事件处理程序将全局处理任务引发的所有异常,但仅在它们被 GC 处理后(不是立即处理):
TaskScheduler.UnobservedTaskException += (sender, args) => HandleException(args.Exception);
我有一个场景,我创建 Tasks 作为 Webapi 调用的一部分。当任务中发生异常时,它不会被捕获,我不知道如何为此实现全局异常处理程序。
特别是:
- This question and the solution for Web API Global Error Handling 不适用于任务。我猜是因为这些是在 webapi 不知道的线程上执行的。
- 正在订阅 AppDomain.UnhandledException Event does not work either。可能是因为虚拟主机捕获所有未处理的异常并且不让它们冒泡。
如果您认为上述任何方法都有效,请告诉我,我会提出一个我观察到的可重现的小例子。否则,这样做的正确方法是什么?
[HttpGet]
public IQueryable<Thingies> Thingies()
{
Task.Run(() => { throw new ApplicationException("How do I catch all of these globally?"); });
return _db.Thingies;
}
我还要注意,该应用程序不依赖于 System.Web
,我不想介绍它们。
使用async-await而不是直接使用Task,异常处理会很简单如下:
try
{
// Asynchronous implementation.
await Task.Delay(1000);
}
catch (Exception ex)
{
// Handle exceptions.
}
或者,如果您仍然需要使用任务,则按照此处所述继续使用:How to manage properly an exception in a Task with ContinueWith
从 运行 任务内部抛出的异常不会得到处理。他们在那个任务上被捕获,导致它出错。
处理这些异常的正确方法是等待每个任务,或使用 Task.ContinueWith
注册延续。但是,如果您想要一个全局处理程序,您可以使用 TaskScheduler.UnobservedTaskException
事件。
当任务中出现异常时,它会被处理并存储在 Task
对象中供您观察。如果任务被垃圾收集并且异常还没有被任何代码观察到,.Net 知道它永远不会被观察到(因为你没有对任务的引用)并引发 TaskScheduler.UnobservedTaskException
事件(在.Net 4.0 它也会使应用程序崩溃,并且这种行为也可以在较新的版本中复制。
因此,TaskScheduler.UnobservedTaskException
的事件处理程序将全局处理任务引发的所有异常,但仅在它们被 GC 处理后(不是立即处理):
TaskScheduler.UnobservedTaskException += (sender, args) => HandleException(args.Exception);