catch exception that is thrown in different thread catch exception that is thrown in different thread multithreading multithreading

catch exception that is thrown in different thread


In .NET 4 and above, you can use Task<T> class instead of creating new thread. Then you can get exceptions using .Exceptions property on your task object.There are 2 ways to do it:

  1. In a separate method: // You process exception in some task's thread

    class Program{    static void Main(string[] args)    {        Task<int> task = new Task<int>(Test);        task.ContinueWith(ExceptionHandler, TaskContinuationOptions.OnlyOnFaulted);        task.Start();        Console.ReadLine();    }    static int Test()    {        throw new Exception();    }    static void ExceptionHandler(Task<int> task)    {        var exception = task.Exception;        Console.WriteLine(exception);    }}
  2. In the same method: // You process exception in the caller's thread

    class Program{    static void Main(string[] args)    {        Task<int> task = new Task<int>(Test);        task.Start();        try        {            task.Wait();        }        catch (AggregateException ex)        {            Console.WriteLine(ex);            }        Console.ReadLine();    }    static int Test()    {        throw new Exception();    }}

Note that the exception which you get is AggregateException. All real exceptions are availible through ex.InnerExceptions property.

In .NET 3.5 you can use the following code:

  1. // You process exception in the child's thread

    class Program{    static void Main(string[] args)    {        Exception exception = null;        Thread thread = new Thread(() => SafeExecute(() => Test(0, 0), Handler));        thread.Start();                    Console.ReadLine();    }    private static void Handler(Exception exception)    {                Console.WriteLine(exception);    }    private static void SafeExecute(Action test, Action<Exception> handler)    {        try        {            test.Invoke();        }        catch (Exception ex)        {            Handler(ex);        }    }    static void Test(int a, int b)    {        throw new Exception();    }}
  2. Or // You process exception in the caller's thread

    class Program{    static void Main(string[] args)    {        Exception exception = null;        Thread thread = new Thread(() => SafeExecute(() => Test(0, 0), out exception));        thread.Start();                    thread.Join();        Console.WriteLine(exception);            Console.ReadLine();    }    private static void SafeExecute(Action test, out Exception exception)    {        exception = null;        try        {            test.Invoke();        }        catch (Exception ex)        {            exception = ex;        }    }    static void Test(int a, int b)    {        throw new Exception();    }}


You can not catch the exception in Method1. You can, however, catch the exception in Method2 and record it to a variable that the original thread of execution can then read and work with.


The simplest method to share data between different threads is shared data as follows (some is pseudo code):

class MyThread{   public string SharedData;   public void Worker()   {      ...lengthy action, infinite loop, etc...      SharedData = "whatever";      ...lengthy action...      return;   }}class Program{   static void Main()   {      MyThread m = new MyThread();      Thread WorkerThread = new Thread(m.Worker);      WorkerThread.Start();      loop//or e.g. a Timer thread      {         f(m.SharedData);      }      return;   }}

You can read about this method in this nice introduction about multithreading, however, I preferred to read about this in the O'Reilly book C# 3.0 in a nutshell, by the brothers Albahari (2007), which is also freely accessible on Google Books, just like the newer version of the book, because it also covers thread pooling, foreground versus background threads, etc etc, with nice and simple example code. (Disclaimer: I own a worn-out copy of this book)

In case you are making a WinForms application, the use of shared data is especially handy, because the WinForm controls are not thread-safe. Using a callback to pass data from the worker thread back to a WinForm control the main UI thread needs ugly code with Invoke() to make that control thread-safe. Using shared data instead, and the single-threaded System.Windows.Forms.Timer, with a short Interval of say 0.2 seconds, you can easily send information from the worker thread to the control without Invoke.