解码(.NET 4.5之前)异步/等待堆栈跟踪

10

由于.NET 4.5之前的运行时(包括SL/WP)不支持异步,它们生成的堆栈跟踪会显示编译器生成的类/方法名称(例如d_15)。

有没有人知道一种工具,可以根据运行时堆栈跟踪、程序集和pdb文件生成更好的堆栈跟踪?

明确一点:我不是在寻找完整的异步堆栈,只是希望查看实际引发异常的方法

似乎上述语句并不清晰,因此这里提供一个示例:

public async void Foo()
{
    await Bar();
}

public async Task Bar()
{
    async SomethingToMakeThisMethodAsync();

    throw new Exception()
}

当抛出异常时,堆栈跟踪将仅包含生成的方法名称(d_15())。我不关心Foo调用了Bar。我只想知道抛出异常的方法是Bar。

2个回答

4

谢谢Peter,这对于追踪_async_链可能非常有用,但我只是想要在异常发生时的实际(同步)堆栈的未混淆堆栈跟踪 - 我知道它会停在第一个异步边界。 - Richard Szalay
1
例如,如果我看到异常提到了 d_12(),我可以使用 ILSpy 工具反编译程序集并禁用 await 支持来找出它所在的方法。我需要的是一种能够为我执行该任务的工具。 - Richard Szalay

1

看起来你在赏金上浪费了你的声望,因为这个问题之前已经被问过几次,例如:

我记得这个问题曾经有几个赏金,但没有比这更进一步的参考:

或者在这个SO问题中:

参考答案:

另一个类似的SO问题:

我发现Daniel Moth在Visual Studio 2010中关于并行调试(Parallel Stacks,Parallel Tasks)的参考资料集非常有帮助。

更新:

运行您的代码后

using System;
using System.Threading.Tasks;

namespace ConsoleApplication1
{
  class Program
  {
    static void Main(string[] args)
    {
        Foo();
    }
    public static async void Foo()
    {
      await Bar();
    }

    public static async Task Bar()
    {
      try
      {
        //async SomethingToMakeThisMethodAsync();
        //to make this async
        await TaskEx.Delay(2000);//await Task.Delay(2000);//in .NET 4.5
        throw new Exception();
      }
      catch (Exception)
      {
        throw new Exception("This is Excptn in Bar() method");
      }
    }
  }
}

在VS2010+Async CTP调试模式(F5)中,我清楚地看到了我的标识异常消息“This is Excptn in Bar() method”:

enter image description here

enter image description here

无论如何,在堆栈跟踪(局部窗口)中,即使没有任何附加标记(使用自定义消息捕获并重新抛出异常),它也被识别为ConsoleApplication1.Program.<Bar>,即在上述代码中将Bar()方法替换为:
public static async Task Bar()
{
    //async SomethingToMakeThisMethodAsync();
    //to make this async
     await TaskEx.Delay(2000);//await Task.Delay(2000);//in .NET 4.5
     throw new Exception();
}

我在堆栈跟踪中看到异常是在ConsoleApplication1.Program.<Bar>中抛出的:

+ $exception    
{System.Exception: Exception of type 'System.Exception' was thrown.

Server stack trace: 
   at ConsoleApplication1.Program.<Bar>d__3.MoveNext() in R:\###Debugging\#seUnmangling (pre .NET 4.5) asyncawait stack traces\AsyncConsole_Sln\1Cons_Prj\Program.cs:line 29

Exception rethrown at [0]: 
   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter.ValidateEnd(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter.GetResult()
   at ConsoleApplication1.Program.<Foo>d__0.MoveNext() in R:\###Debugging\#seUnmangling (pre .NET 4.5) asyncawait stack traces\AsyncConsole_Sln\1Cons_Prj\Program.cs:line 19

Exception rethrown at [1]: 
   at System.Runtime.CompilerServices.AsyncVoidMethodBuilder.<SetException>b__1(Object state)
   at System.Threading.QueueUserWorkItemCallback.WaitCallback_Context(Object state)
   at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean ignoreSyncCtx)
   at System.Threading.QueueUserWorkItemCallback.System.Threading.IThreadPoolWorkItem.ExecuteWorkItem()
   at System.Threading.ThreadPoolWorkQueue.Dispatch()
   at System.Threading._ThreadPoolWaitCallback.PerformWaitCallback()}   System.Exception

enter image description here


我并没有浪费我的声望 - 人们一直拒绝阅读我问题中的“明确说明”部分。我不是在寻找异步调用堆栈。 我想知道当前异步方法正在执行哪个方法。我将再次更新我的问题以使其更加清晰明了。 - Richard Szalay
1
你可以通过识别方法的消息(参见我的答案更新)捕获并重新抛出异常。 - Gennady Vanin Геннадий Ванин

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接