Code sample:
using System;
using System.Threading.Tasks;
public class Program
{
public static void Main()
{
Console.WriteLine("Start");
Foo f = new Foo();
f.FooAsync();
}
public class Foo
{
public async void FooAsync()
{
try
{
await Task.Run(() =>
{
Console.WriteLine("Throwing");
throw new Exception();
});
}
catch (Exception)
{
Console.WriteLine("Caught");
}
}
}
}
The above code when run from C# fiddle or from the console on my PC prints:
Start
Throwing
Caught
C# Fiddle Example
However, when I run it from Visual Studio (F5 in debug mode), I get the following message:
I don't understand why I get "was not handled in user code" message from Visual Studio although running it from the console or C# fiddle is fine. Am I missing something obvious?
UPDATE
I've tried waiting on the task f.FooAsync().Wait();
in Main, but the exception is still reported as being unhandled (same error message).
When exceptions happen, all the exceptions are re-thrown by the calling thread. To do that they're wrapped inside AggregateException and returned to the caller. So when we await a task, we only get the first exception from a collection of exceptions that might exist on a task.
To turn off stop on exceptions press " Ctrl + Alt + E ". This will open the Exceptions window . Untick "Common Language Runtime Exceptions - Thrown". That would prevent it from pausing from within the delegate, but not when it's rethrown on Wait .
First, what's special about this exception is that it's being thrown from Task.Run
and for that scope, the exception really isn't handled by user-code.
The framework catches and stores the exception in the returned task for you to handle later, if you fail to do that it's an unobserved task exception (which in .Net 4.0 would've crashed the application).
The issue here is the "Enable Just My Code" feature in the settings. When the feature is turned on the debugger breaks on exceptions when you leave user-code and enter framework-code and at that point the exception really wasn't handled.
If you turn that feature off the debugger will not break on that exception as it will follow your code into the framework and see the exception being handled and stored in the task. The exception will then be re-thrown when you await
the task and be handled by your code.
Since the handling that actually matters is the one being done by the framework, this is an even simpler example:
public static void Main()
{
Task.Run(() =>
{
throw new Exception();
});
Console.ReadLine();
}
With "Enable Just My Code" turned on the debugger will break on the exception, without it the debugger will not.
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