Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Throwing exception from Task.Run displays "Not Handled from User Code" Message

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:

Exception Picture

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).

like image 208
Jesse Good Avatar asked Jun 06 '15 07:06

Jesse Good


People also ask

What happens when a task throws an exception?

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.

How do I stop Visual Studio from breaking on exception?

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 .


1 Answers

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.

like image 191
i3arnon Avatar answered Oct 19 '22 20:10

i3arnon