KDecker
KDecker

Reputation: 7128

Catching exceptions thrown within a Task?

I am trying to catch exceptions within a Task I have created but they never "bubble up" to where the Task is ran from, they are always caught by Visual Studio as runtime errors.

Here is a SSCCE I have created to show the issue

using System;
using System.Threading.Tasks;

namespace ConsoleApplicationSandbox
{
    class Program
    {
        static void Main(string[] args)
        {
            CreateTheIssue();
            Console.ReadLine();
        }

        public static async void CreateTheIssue()
        {
            try
            {
                int val = await ExceptionThrowerClass.DoSomething();
            }
            catch(Exception ex)
            {
                Console.Out.WriteLine("Exception of type " + ex.GetType() + " caught, message: " + ex.Message);
            }
        }
    }

    public static class ExceptionThrowerClass
    {
        public static Task<int> DoSomething()
        {
            return Task.Run(() =>
            {
                throw new FooException("How exceptional!");
                return 1;
            });
        }
    }

    public class FooException : Exception
    {
        public FooException() : base () { }
        public FooException(String message) : base(message) { }
        public FooException(String message, Exception inner) : base (message, inner) { }
    }
}

Visual Studio notifies me when I throw FooExcepion in DoSomething that the exception is not being caught. From this SO answer and this MSDN page I thought that the exceptions would just "bubble up" to myTask.Wait() and subsequently be caught. Though this does not seem to be that case.

The project settings for this SCCEE are targeting .NET 4.5.2 and I am using Visual Studio 2015. Is it that my targeted .NET framework cannot catch exceptions in this manner? How can I catch FooException in the try/catch block within Main?

EDIT: I have altered the SSCCE to use the async/await pattern instead of Task.Wait.

Upvotes: 1

Views: 401

Answers (1)

Scott Chamberlain
Scott Chamberlain

Reputation: 127543

Hit the Continue button, you will see that the exception does get caught in the outer try/catch. Because the exception crossed in to the innards of Task the exception was considered "User Unhanded", however Task handels it for you by putting the task in to the Faulted state. This will a exception to be re-raised when you await or .Wait() the task.

Using your original method before your edit would need to do

    try
    {
        myTask.Wait();
    }
    catch(AggregateException ex)
    {
        var innerException = ex.InnerException;
        Console.Out.WriteLine("Exception of type " + innerException .GetType() + " caught, message: " + innerException.Message);
    }

Because the Task will wrap the exceptions up in to a AggregateException, when you use await it unwraps the exception for you.

Upvotes: 2

Related Questions