Unmangling(.NET 4.5之前版本)异步/等待堆栈跟踪

时间:2013-05-05 23:32:55

标签: visual-studio debugging exception-handling stack-trace async-await

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

有没有人知道在给定运行时堆栈跟踪,程序集和pdb的情况下生成更好的堆栈跟踪的实用程序?

要明确:我不是在寻找一个完整的异步堆栈,只是更好地了解实际抛出异常的方法

上面的陈述似乎不够清楚,所以这里有一个例子:

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

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

    throw new Exception()
}

当抛出异常为Bar时,堆栈跟踪将仅包含生成的方法名称(d_15())。 我不在乎Foo叫Bar。我只是想知道Bar是抛出异常的方法

2 个答案:

答案 0 :(得分:4)

Andrew Stasyuk在MSDN杂志http://msdn.microsoft.com/en-us/magazine/jj891052.aspx中发表了一篇很棒的文章,详细介绍了Async Causality Chains,它是一种根据不相交和混乱的堆栈跟踪来帮助调试的方法。

答案 1 :(得分:1)

好像你浪费了你的代表,因为这个问题之前被问过几次,例如:

我记得,其中很少有赏金,但没有比参考更多:

或者在这个SO问题中:

参考答案:

另一个类似的问题:

我发现Daniel Moth在Visual Studio 2010中Parallel Debugging(并行堆栈,并行任务)上的引用集合非常有用

更新

运行代码

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 +异步CTP调试模式(F5)中,我清楚地看到我的识别异常消息“这是Bar()方法中的Excptn”:

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