It's clear why stack traces are affected with Microsoft's new programming paradigm. We now have a semantic stack and a couple of physical ones (my choice of words).
What I get to see is an exception's StackTrace
property (and in the debugger) is the physical ones, concatenated:
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)); }
This gives:
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
My question is: Is there a (convenient, standard) way to convert this to a proper backtrace in the semantic sense, such as:
CheckFooAndBar Foo Bar
Of course there could be a mixture of awaits and inline path fragments in the stack.
I tried looking at the stack as it is with .NET 4.5 and SL5 with the async targetting pack, but not yet with WinRT. The output is from .NET 4.5.
In SL5, which is what I mainly do, the situation is more problematic: You don't get line numbers in stack traces in Silverlight (even with elevated privileges), which makes the need for context more important.
Asynchronous stack traces allow you to inspect function calls beyond the current event loop. This is particularly useful because you can examine the scope of previously executed frames that are no longer on the event loop. This feature is currently an experiment and needs to be enabled.
Async/await and then() are very similar. The difference is that in an async function, JavaScript will pause the function execution until the promise settles. With then() , the rest of the function will continue to execute but JavaScript won't execute the .
JavaScript language features in Node 12js now tracks the asynchronous call frames in the error. stack property.
Promise creation starts the execution of asynchronous functionality. await only blocks the code execution within the async function. It only makes sure that the next line is executed when the promise resolves. So, if an asynchronous activity has already started, await will not have any effect on it.
With Visual Studio 2013 and .NET 4.5.1, this problem appears to be addressed - and not only in .NET.
Further Reading: Debugging Asynchronous Code in Visual Studio 2013 - Call Stack enhancements.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With