I have a C# console application project using .NET 4.0, with the Microsoft.Bcl.Async package installed. I use this code:
internal class Program
{
private static void Main(string[] args)
{
Foo().Wait();
}
static void Log(Exception ex)
{
}
private static async Task Foo()
{
try
{
await DoSomething();
}
catch (Exception ex)
{
Log(ex);
}
}
private static async Task DoSomething()
{
throw new DivideByZeroException();
}
}
If I put a breakpoint inside of the Log method, I get my DivideByZero exception, but the stack trace I see is:
at Microsoft.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at Microsoft.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccess(Task task)
at Microsoft.Runtime.CompilerServices.TaskAwaiter.ValidateEnd(Task task)
at Microsoft.Runtime.CompilerServices.TaskAwaiter.GetResult()
at AsyncStacks.Program.<Foo>d__0.MoveNext() in p:\Sandbox\AsyncStacks\AsyncStacks\Program.cs:line 25
This stack trace is next to useless as it doesn't tell me where the exception was actually thrown.
If I change my project to target .NET 4.5, I get a more useful exception:
at AsyncStacks.Program.<DoSomething>d__3.MoveNext() in p:\Sandbox\AsyncStacks\AsyncStacks\Program.cs:line 35
--- 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 AsyncStacks.Program.<Foo>d__0.MoveNext() in p:\Sandbox\AsyncStacks\AsyncStacks\Program.cs:line 25
How can I get a useful stack trace from a .NET 4.0 project when using await
?
Update
The "old" AsyncTargetingPack does throw a much better stack trace. The issue seems to have been introduced in the "new" Microsoft.Bcl.Async.
Changing Foo
to this appears to get a better result:
private static async Task Foo()
{
await DoSomething().ContinueWith(t => Log(t.Exception), TaskContinuationOptions.OnlyOnFaulted);
}
Update: However, the downside is you have to use the same .ContinueWith
every time you use the await
keyword. I.e., if you await something that also awaits, you need to .ContinueWith
that too.
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