Last year I wrote about getting good exception stack traces for async code.

Now I've cleaned it up, made into a Portable Class Library, published the source code it under MIT-license on github and made precompiled binaries available as a NuGet package.

 

To recap: the goal is to get a user-experience like this, including line numbers and filenames, even on platforms like Phone which don't ship with PDBs:

 

To use the AsyncStackTraceEx nuget package:

  1. Right-click on your project > Manage NuGet Packages > search for "AsyncStackTraceEx" and install it
      
  2. You can change your Await DownloadAsync(url) statements into Await DownloadAsync(url).Log()
      
  3. You can also provide more information: Await DownloadAsync(url).Log("DownloadAsync",url)
      
  4. When you catch an exception, rather than using Exception.StackTrace, you'll get a more useful actionable callstack with Exception.StackTraceEx()
      

Here's a side-by-side comparison of the output.

Normal Exception.StackTrace
(the highlighted parts are absent on phone since they depend on PDBs)
Using AsyncStackTraceEx
(the highlighted parts are present even on phone)
   at VB$StateMachine_3_BarAsync.MoveNext() in Class1.vb:line 24
--- End of stack trace from previous location where exception was thrown ---
   at TaskAwaiter.ThrowForNonSuccess(Task task)
   at TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at TaskAwaiter.GetResult()
   at VB$StateMachine_2_FooAsync.MoveNext() in Class1.vb:line 19
--- End of stack trace from previous location where exception was thrown ---
   at TaskAwaiter.ThrowForNonSuccess(Task task)
   at TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at TaskAwaiter.GetResult()
   at VB$StateMachine_1_TestAsync.MoveNext() in Class1.vb:line 14
--- End of stack trace from previous location where exception was thrown ---
   at TaskAwaiter.ThrowForNonSuccess(Task task)
   at TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at TaskAwaiter`1.GetResult()
   at VB$StateMachine_0_Button1_Click.MoveNext() in Class1.vb:line 5
   at Test.BarAsync
   at Test.FooAsync()#BarAsync in Class1.vb:19
   at Test.TestAsync()#FooAsync(True) in Class1.vb:14
   at Test.Button1_Click() in Class1.vb:5