Handle your thread errors

If you use Task.Factory.StartNew or one of it’s likes a lot, you may found yourself in the odd situation that exceptions from background threads either get delayed or do not appear at all. This behaviour is rather well described here including special conditions such as backgroundthreads started by other background threads.

The long story short, is that you should observe your exceptions in the parent task. Even if you use a continuation this holds true. The go to place to do exactly that is the point where you wait for task completion. At this point you will receive an aggregateexception that can contain one or more innerexceptions from your code. If you use nested threads, you may even get stacked aggegateexceptions. The below code uses .Flatten() to bring back potentially nedted levels to just one. Which brings us to the following code to effeciently handle background thread exceptions:

Task t = Task.Factory.StartNew(() => DoBackGroundTask());
try {
    Task.WaitAll(t);
}
catch (AggregateException e) {
    Console.WriteLine(e.Message);
    foreach (Exception inner in e.Flatten().InnerExceptions) {
        Console.WriteLine(inner.Message);
    }
}

or, wrapped in a more complete example:

using System;
using System.Threading.Tasks;

namespace TaskExceptionDemo {
    internal class Program {

        /// <summary>
        ///     This will throw a devision by zero error
        /// </summary>
        private static void DoBackGroundTask() {
            int x = 10;
            int y = 0;
            Console.WriteLine(x / y);
        }

        private static void Main(string[] args) {
            Console.WriteLine("start background work");
            Task t = Task.Factory.StartNew(() => DoBackGroundTask());
            try {
                Task.WaitAll(t);
            }
            catch (AggregateException e) {
                Console.WriteLine(e.Message);
                foreach (Exception inner in e.Flatten().InnerExceptions) {
                    Console.WriteLine(inner.Message);
                }
            }
            Console.WriteLine("work ended.");
            Console.ReadLine();
        }

    }
}