[英]Debugging exceptions in a Async/Await (Call Stack)
我使用Async / Await釋放我的UI-Thread並完成多線程。 我遇到異常時遇到問題。 我的Async部件的Call Stack
總是從ThreadPoolWorkQue.Dipatch()
開始,這對我沒什么幫助。
我找到了MSDN文章Andrew Stasyuk。 Async Causality Chain跟蹤它,但據我了解,它不是一個隨時可用的解決方案。
如果在Async / Await中使用多線程,最好/最簡單的調試方法是什么?
您找到的文章很好地解釋了為什么調用堆棧不像我們大多數人認為的那樣工作。 從技術上講,調用堆棧只告訴我們在當前方法之后代碼返回的位置。 換句話說,調用堆棧是“代碼進行的地方”,而不是“代碼來自哪里”。
有趣的是,文章確實提到了一個解決方案,但沒有對其進行闡述。 我有一篇博文,詳細解釋了CallContext
解決方案 。 實質上,您使用邏輯調用上下文來創建自己的“診斷上下文”。
我喜歡CallContext
解決方案比文章中提供的解決方案更好,因為它確實可以工作所有形式的async
代碼(包括像Task.WhenAll
這樣的fork / join代碼)。
這是我所知道的最佳解決方案(除了做一些非常復雜的事情,比如掛鈎到分析API)。 CallContext
方法的注意事項:
代碼(取決於不可變集合NuGet庫 ):
public static class MyStack
{
private static readonly string name = Guid.NewGuid().ToString("N");
private static ImmutableStack<string> CurrentContext
{
get
{
var ret = CallContext.LogicalGetData(name) as ImmutableStack<string>;
return ret ?? ImmutableStack.Create<string>();
}
set
{
CallContext.LogicalSetData(name, value);
}
}
public static IDisposable Push([CallerMemberName] string context = "")
{
CurrentContext = CurrentContext.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;
}
}
// Keep this in your watch window.
public static string CurrentStack
{
get
{
return string.Join(" ", CurrentContext.Reverse());
}
}
}
用法:
static async Task SomeWorkAsync()
{
using (MyStack.Push()) // Pushes "SomeWorkAsync"
{
...
}
}
更新:我發布了一個NuGet包(在我的博客上描述) ,它使用PostSharp自動注入推送和彈出。 因此,獲得良好的痕跡現在應該更加簡單。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.