Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

TimeoutException, TaskCanceledException C#

I am new to C# and I find exceptions a bit confusing... I have a web app with the following code:

try
{
    //do something
}
catch (TimeoutException t)
{
    Console.WriteLine(t);
}
catch (TaskCanceledException tc)
{
    Console.WriteLine(tc);
}
catch (Exception e)
{
    Console.WriteLine(e);
}

When I debug the code, it throws the e Exception, the most general one and when I hover over the exception info it turns out that it's the TaskCanceledException. Why isnt the TaskCanceledException caught? If the exception was a TimeoutException would it catch the TimeoutException or would it also catch the Exception? Why is that?

like image 874
Marta Avatar asked Jul 21 '14 13:07

Marta


1 Answers

When catching an Exception, you have to make sure it is exactly the exception being thrown. When using Task.Run or Task.Factory.Startnew and generally involving an exception being thrown from a Task (unless the task is being awaited with the await keyword), the outer exception you're dealing with is an AggregateException, because a Task unit may have child tasks which may also throw exceptions.

From Exception Handling (Task Parallel Library):

Unhandled exceptions that are thrown by user code that is running inside a task are propagated back to the joining thread, except in certain scenarios that are described later in this topic. Exceptions are propagated when you use one of the static or instance Task.Wait or Task.Wait methods, and you handle them by enclosing the call in a try-catch statement. If a task is the parent of attached child tasks, or if you are waiting on multiple tasks, then multiple exceptions could be thrown. To propagate all the exceptions back to the calling thread, the Task infrastructure wraps them in an AggregateException instance. The AggregateException has an InnerExceptions property that can be enumerated to examine all the original exceptions that were thrown, and handle (or not handle) each one individually. Even if only one exception is thrown, it is still wrapped in an AggregateException.

So, in order to deal with that, you have to catch AggregateException:

try
{
    //do something
}
catch (TimeoutException t)
{
    Console.WriteLine(t);
}
catch (TaskCanceledException tc)
{
    Console.WriteLine(tc);
}
catch (AggregateException ae)
{
   // This may contain multiple exceptions, which you can iterate with a foreach
   foreach (var exception in ae.InnerExceptions)
   {
       Console.WriteLine(exception.Message);
   }
}
catch (Exception e)
{
    Console.WriteLine(e);
}
like image 58
Yuval Itzchakov Avatar answered Oct 20 '22 06:10

Yuval Itzchakov