首先,堆栈跟踪并不像大多数人认为的那样。它们在调试期间很有用,但不适用于运行时使用,特别是在 ASP.NET 上。
另外,堆栈跟踪在技术上是关于代码返回到的位置, not 代码来自哪里。对于简单(同步)代码,两者是相同的:代码总是返回到调用它的任何方法。但是,对于异步代码,这两者是不同的。同样,堆栈跟踪告诉您将会发生什么next,但你对发生的事情感兴趣past.
因此,堆栈帧并不是满足您需求的正确答案。埃里克·利珀特(Eric Lippert)在他的回答中对此做了很好的解释 https://stackoverflow.com/a/15368508/263693.
The MSDN 文章 http://msdn.microsoft.com/en-us/magazine/jj891052.aspx@ColeCampbell 链接到的描述了一种跟踪“伤亡链”(代码来自的地方)的方法from) with async
代码。不幸的是,这种方法是有限的(例如,它不能处理分叉/连接场景);然而,据我所知,这是唯一适用于 Windows 应用商店应用程序的方法。
由于您使用的是具有完整 .NET 4.5 运行时的 ASP.NET,因此您可以使用更强大的解决方案来跟踪事故链:逻辑调用上下文。你的async
不过,方法确实必须“选择加入”,因此您不能像堆栈跟踪那样免费获得它。我刚刚在一篇尚未发布的博客文章中写了这篇文章,所以您可以预览一下。 :)
您可以围绕逻辑调用上下文自行构建调用“堆栈”,如下所示:
public static class MyStack
{
// (Part A) Provide strongly-typed access to the current stack
private static readonly string slotName = Guid.NewGuid().ToString("N");
private static ImmutableStack<string> CurrentStack
{
get
{
var ret = CallContext.LogicalGetData(name) as ImmutableStack<string>;
return ret ?? ImmutableStack.Create<string>();
}
set { CallContext.LogicalSetData(name, value); }
}
// (Part B) Provide an API appropriate for pushing and popping the stack
public static IDisposable Push([CallerMemberName] string context = "")
{
CurrentStack = CurrentStack.Push(context);
return new PopWhenDisposed();
}
private static void Pop() { CurrentContext = CurrentContext.Pop(); }
private sealed class PopWhenDisposed : IDisposable
{
private bool disposed;
public void Dispose()
{
if (disposed) return;
Pop();
disposed = true;
}
}
// (Part C) Provide an API to read the current stack.
public static string CurrentStackString
{
get { return string.Join(" ", CurrentStack.Reverse()); }
}
}
(ImmutableStack
可用here https://nuget.org/packages/Microsoft.Bcl.Immutable)。然后你可以像这样使用它:
static async Task SomeWork()
{
using (MyStack.Push())
{
...
Console.WriteLine(MyStack.CurrentStackAsString + ": Hi!");
}
}
这种方法的好处是它可以与all async
代码:fork/join,自定义等待,ConfigureAwait(false)
等等。缺点是您增加了一些开销。另外,这种方法仅适用于 .NET 4.5; .NET 4.0 上的逻辑调用上下文不是async
- 意识到并愿意not正常工作。
Update:我发布了一个NuGet 包(在我的博客中描述) http://blog.stephencleary.com/2013/05/announcement-async-diagnostics.html使用 PostSharp 自动注入推送和弹出操作。因此,现在获得良好的跟踪应该容易得多。