スタックトレースがMicrosoftの新しいプログラミングパラダイムの影響を受ける理由は明らかです。これで、セマンティックスタックといくつかの物理スタック(私の選択した単語)ができました。
私が見るのは、例外のStackTrace
プロパティ(およびデバッガー内)が物理的なものであり、連結されていることです:
private async Task CheckFooAndBar()
{
var log = LogManager.GetLogger("Test");
log.Info("CheckFooAndBar");
try
{
await Foo();
}
catch (Exception ex)
{
log.Info("StackTrace of last exception: " + ex.StackTrace);
}
Console.ReadKey();
}
private async Task Foo()
{
await Task.Factory.StartNew(() => Thread.Sleep(1000));
await Bar();
await Task.Factory.StartNew(() => Thread.Sleep(1000));
}
private async Task Bar()
{
await Task.Factory.StartNew(() => Thread.Sleep(1000));
throw new Exception();
await Task.Factory.StartNew(() => Thread.Sleep(1000));
}
これは与える:
StackTrace of last exception: at NLogAsyncExceptionTestCase.Program.<Bar>d__d.MoveNext() in c:\Users\Jens\Documents\Visual Studio 2012\Projects\NLogAsyncExceptionTestCase\NLogAsyncExceptionTestCase.Console\Program.cs:line 53
--- 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.TaskAwaiter.GetResult()
at NLogAsyncExceptionTestCase.Program.<Foo>d__8.MoveNext() in c:\Users\Jens\Documents\Visual Studio 2012\Projects\NLogAsyncExceptionTestCase\NLogAsyncExceptionTestCase.Console\Program.cs:line 44
--- 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.TaskAwaiter.GetResult()
at NLogAsyncExceptionTestCase.Program.<CheckFooAndBar>d__0.MoveNext() in c:\Users\Jens\Documents\Visual Studio 2012\Projects\NLogAsyncExceptionTestCase\NLogAsyncExceptionTestCase.Console\Program.cs:line 30
私の質問は次のとおりです。セマンティックな意味でこれを適切なバックトレースに変換する(便利で標準的な)方法はありますか。
CheckFooAndBar
Foo
Bar
もちろん、スタック内に待機とインラインパスフラグメントが混在する可能性があります。
非同期ターゲットパックを使用した.NET 4.5およびSL5でのスタックを見てみましたが、WinRTではまだそうではありません。出力は.NET 4.5からです。
私が主に行っているSL5では、状況はより問題になります。Silverlightのスタックトレースで行番号を取得できないため(特権が昇格されている場合でも)、コンテキストの必要性がより重要になります。
Visual Studio 2013および.NET 4.5.1では、この問題は.NETだけでなく対処されているようです。
詳細については、 このブログ投稿 を参照してください。