是否可以使用 .NET 异步方法获得良好的堆栈跟踪? [英] Is it possible to get a good stack trace with .NET async methods?

查看:21
本文介绍了是否可以使用 .NET 异步方法获得良好的堆栈跟踪?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在 WebApi 应用程序中设置了以下示例代码:

I have the following sample code setup in a WebApi application:

[HttpGet]
public double GetValueAction()
{
    return this.GetValue().Result;
}

public async Task<double> GetValue()
{
    return await this.GetValue2().ConfigureAwait(false);
}

public async Task<double> GetValue2()
{
    throw new InvalidOperationException("Couldn't get value!");
}

遗憾的是,当 GetValueAction 被命中时,返回的堆栈跟踪是:

Sadly, when GetValueAction gets hit, the stack trace that comes back is:

    " at MyProject.Controllers.ValuesController.<GetValue2>d__3.MoveNext() in c:devMyProjectMyProjectControllersValuesController.cs:line 61 --- 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.Runtime.CompilerServices.ConfiguredTaskAwaitable`1.ConfiguredTaskAwaiter.GetResult()
at MyProject.Controllers.ValuesController.<GetValue>d__0.MoveNext() in c:devMyProjectMyProjectControllersValuesController.cs:line 56"

因此,我在跟踪中得到了(损坏的)GetValue2 和 GetValue,但没有提到 GetValueAction.难道我做错了什么?是否有另一种模式可以让我获得更完整的堆栈跟踪?

Thus, I get (mangled) GetValue2 and GetValue in the trace, but no mention of GetValueAction. Am I doing something wrong? Is there another pattern that will get me more complete stack traces?

我的目标不是编写依赖堆栈跟踪的代码,而是使异步方法中的故障更容易调试.

my goal is not to write code relying on the stack trace, but instead to make failures in async methods easier to debug.

推荐答案

这个问题及其得票最高的答案是在 2013 年写的.从那时起情况有所改善.

This question and its highest voted answer were written back in 2013. Things have improved since then.

.NET Core 2.1 现在提供了开箱即用的可理解的异步堆栈跟踪;请参阅 .NET 中的 Stacktrace 改进核心 2.1.

.NET Core 2.1 now provides intelligible async stack traces out of the box; see Stacktrace improvements in .NET Core 2.1.

对于那些仍然使用 .NET Framework 的人来说,有一个出色的 NuGet 包可以修复堆栈跟踪中的异步(和许多其他模糊问题):Ben.Demystifier.这个包相对于其他建议的优势在于它不需要更改抛出的代码或程序集;您只需在捕获的异常上调用 DemystifyToStringDemystified 即可.

For those still on .NET Framework, there's an excellent NuGet package that fixes up async (and many other obscurities) in stack traces: Ben.Demystifier. The advantage of this package over other suggestions is that it doesn't require changes to the throwing code or assembly; you simply have to call Demystify or ToStringDemystified on the caught exception.

将此应用于您的代码:

System.AggregateException: One or more errors occurred. ---> System.InvalidOperationException: Couldn't get value!
   at async Task<double> ValuesController.GetValue2()
   at async Task<double> ValuesController.GetValue()
   --- End of inner exception stack trace ---
   at void System.Threading.Tasks.Task.ThrowIfExceptional(bool includeTaskCanceledExceptions)
   at TResult System.Threading.Tasks.Task<TResult>.GetResultCore(bool waitCompletionNotification)
   at TResult System.Threading.Tasks.Task<TResult>.get_Result()
   at double ValuesController.GetValueAction()
   at void Program.Main(string[] args)
---> (Inner Exception #0) System.InvalidOperationException: Couldn't get value!
   at async Task<double> ValuesController.GetValue2()
   at async Task<double> ValuesController.GetValue()<---

由于您使用了Task<T>.Result,这确实有点令人费解.如果您将 GetValueAction 方法转换为异步(本着 一路异步),你会得到预期的干净结果:

This is admittedly still a bit convoluted due to your use of Task<T>.Result. If you convert your GetValueAction method to async (in the spirit of async all the way), you would get the expected clean result:

System.InvalidOperationException: Couldn't get value!
   at async Task<double> ValuesController.GetValue2()
   at async Task<double> ValuesController.GetValue()
   at async Task<double> ValuesController.GetValueAction()

这篇关于是否可以使用 .NET 异步方法获得良好的堆栈跟踪?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆