【问题标题】:Debugging Exceptions in Async Code调试异步代码中的异常
【发布时间】:2014-01-08 18:42:42
【问题描述】:

当我在使用 ASP.NET MVC 3 的代码中使用同步方法时,如果抛出异常,不难在我的异常过滤器中找出它来自哪里。只需查看堆栈跟踪就足够了。

但是,当 ASP.NET Web API 中的 async 方法引发异常时,异常详细信息的用处不大,因为堆栈跟踪不会显示异常是从哪里引发的:

System.ArgumentException: title must not be empty.
Parameter name: title    
at System.Web.Http.Filters.ActionFilterAttribute.<CallOnActionExecutedAsync>d__1.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at System.Web.Http.Controllers.ActionFilterResult.<ExecuteAsync>d__2.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at System.Web.Http.ApiController.<InvokeActionWithExceptionFilters>d__1.MoveNext()

目前,我必须查看此消息的所有异常,并根据请求 URI 猜测引发了哪些异常以及幕后发生的情况,或者尝试使用附加的调试器在本地重现错误。

MSDN 有一篇文章详细介绍了获得伤亡链的几种策略:http://msdn.microsoft.com/en-us/magazine/jj891052.aspx3。根据我的理解,我有两个选择:

  • 使用 System.Diagnostics.EventListener 并在运行时降低性能
  • 创建一个扩展方法并将其用于每个await 调用

是否有更好的方法来记录有关引发此异常的更多有用详细信息?拥有伤亡链会很好,但只要获取异常源就可以了(这是抛出的类型和方法)。

【问题讨论】:

  • 仅供参考...我们在 5.0 后进行了改进,其中保留了堆栈跟踪,您可以获得更好的详细信息..
  • @KiranChalla 太棒了!期待这方面的改进。

标签: c# asp.net .net asp.net-web-api async-await


【解决方案1】:

您的两个选项都会导致运行时开销。

第三个选项(也会导致运行时开销)是使用我的AsyncDiagnostics 库。我偏爱那个(自然),但每个选项都会引入运行时开销。

【讨论】:

  • 看起来该库依赖于 PostSharp。你的库有没有这个依赖的版本?
  • @Dustin:不。它使用 Postshap 在 async 方法周围注入钩子。
  • 我将无法使用 PostSharp,因此我将使用我链接到的 MSDN 文章中推荐的方法之一。我会将此标记为已接受,因为您间接回答了我的问题:没有一种方法可以在不采用第三方依赖项的情况下在 ASP.NET Web API 中完成我想要的。
【解决方案2】:

如果将程序集的 PDB 部署到部署 DLL 的同一文件夹,则异常堆栈跟踪应包括文件和行号信息。特别是,MoveNext() 调用将位于您的 async 方法中。

如果为您的程序集启用了优化(并且可能是针对发布版本),行号可能偶尔会不准确,因此如果您仍然无法根据它告诉的行号找出问题,请记住这一点你。

【讨论】:

  • 不幸的是,在这种情况下似乎没有。 PDB 当前部署到运行此代码的服务器上。我在传递给我的异常过滤器的异常中得到的只是上面详述的堆栈跟踪。
【解决方案3】:

针对 .NET 4.5.1 而不是 4.5 进行编译,您通常会通过异步获得更好的异常跟踪。

【讨论】:

  • 就是这样!在服务器上更新 .NET 后,我现在获得了堆栈跟踪,其中包含有关引发异常的位置的更多信息。
猜你喜欢
  • 2015-04-26
  • 2015-12-04
  • 2014-04-27
  • 2018-09-06
  • 2016-09-17
  • 2014-06-03
  • 1970-01-01
  • 2015-11-22
  • 1970-01-01
相关资源
最近更新 更多