Tag Archives: Exception Handling

Exception Handling in Task Parallel Library

Typically when you are using Task parallel library in .NET, the thread on which task would get executed would be different thread , so if you have  you have try catch blocked wrapped for the Task call and have wait on the task then you can catch the exception but it will not show the original exception which was raised. Take for e.g. below

    class Program
    {
        static void Main(string[] args)
        {
            try
            {
                Worker worker = new Worker();
                var task = Task.Factory.StartNew(worker.DoWork);
                task.Wait();
            }
            catch(Exception ex)
            {
                Console.WriteLine(ex.Message);
                Console.WriteLine(ex.GetType());
            }
            Console.ReadLine();
        }
    }

    public class Worker
    {
        public void DoWork()
        {
            throw new Exception("Testing TPL Library Exception Handling");
        }
    }

In the above case the output would be

One or more errors occurred.
System.AggregateException

To propagate all the exceptions back to the calling thread, the Task infrastructure wraps them in an AggregateException instance. The AggregateException exception 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. You can also handle the original exceptions by using the System.AggregateException.Handle method.
Even if only one exception is thrown, it is still wrapped in an AggregateException exception

So we will modify the code to accommodate the AggregateException

    class Program
    {
        static void Main(string[] args)
        {
            try
            {
                Worker worker = new Worker();
                var task = Task.Factory.StartNew(worker.DoWork);
                task.Wait();
            }
            catch (AggregateException ex)
            {
                foreach (var e in ex.InnerExceptions)
                {
                    Console.WriteLine(e.Message);
                    Console.WriteLine(e.GetType());
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.Message);
                Console.WriteLine(ex.GetType());
            }
            Console.ReadLine();
        }
    }

    public class Worker
    {
        public void DoWork()
        {
            throw new Exception("Testing TPL Library Exception Handling");
        }
    }

 

In this case output would be
Testing TPL Library Exception Handling
System.Exception

HTH

Advertisements

“throw” V/S “throw ex”

Is there a difference between “throw” and “throw ex”?

Yes – throw re-throws the exception that was caught, and preserves the stack trace. throw ex throws the same exception, but resets the stack trace to that method. Unless you want to reset the stack trace (i.e. to shield public callers from the internal workings of your library), throw is generally the better choice, since you can see where the exception originated

In the “throw ex”, the stack trace is truncated, what this means is that when you look at the stack trace, it will look as if the exception originated in your code. This isn’t always the case, particularly if you are bubbling up a CLR generated exception (like a SqlException). This is a problem known as “breaking the stack”, because you no longer have the full stack trace information. This happens because you are in essence creating a new exception to throw.

By using “throw” by itself, you preserve the stack trace information. You can confirm this by looking at the IL generated for these two code blocks. This makes the difference very obvious since in the first example the IL instruction called is “throw” while in the second the instruction is called “rethrow”.

Before you run and change all of your code, there are still places where “throw ex” is appropriate. There are times when you want to add information to the exception that was caught or change it into a more meaningful exception.

To Summarize

  • Only catch exceptions if they are important to you and you need to do some sort of cleanup as a result.
  • If you need to bubble an exception up the chain, use “throw” by itself.
  • If you need to add information to the exception or repackage it, always pass the original exception as the inner exception.