当我在使用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。根据我的理解,我有两个选择:
await
调用有没有更好的方法来记录更多有用的详细信息?拥有伤亡链会很好,但只是获得异常来源就可以了(这是什么类型和方法)。
答案 0 :(得分:3)
这两个选项都会导致运行时开销。
第三个选项(也会导致运行时开销)是使用我的AsyncDiagnostics库。我很偏爱那个(自然),但是每个选项都会引入运行时开销。
答案 1 :(得分:3)
针对.NET 4.5.1而不是4.5进行编译,通常会使用异步获得更好的异常跟踪。
答案 2 :(得分:0)
如果将程序集的PDB部署到部署DLL的同一文件夹,则异常堆栈跟踪应包含文件和行号信息。特别是,MoveNext()
来电将位于您的async
方法中。
如果为您的程序集启用了优化(并且它们可能适用于发布版本),则行号可能偶尔会出现不准确的情况,因此如果您仍然无法根据它告诉的行号找出问题,请记住这一点你。