Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Try/Catch and threading

I have an idea why but I'd like to ask if someone has a good grasp on why the exception raised inside a thread is never caught by the code that started it. Here's some very simple code to demonstrate what I mean:

using System;
using System.Collections.Generic;
using System.Threading;

namespace TestCrash
{
    class Program
    {
        private static void Crash(object control)
        {
            AutoResetEvent are = (AutoResetEvent)(((object[])control)[0]);
            are.Set();
            throw new Exception("Burn baby burn");
        }
        static void Main(string[] args)
        {
            try
            {
                List<WaitHandle> waitHandles = new List<WaitHandle>();
                for (int i = 0; i < 100; i++)
                {
                    AutoResetEvent are = new AutoResetEvent(false);
                    waitHandles.Add(are);
                    object[] procControl = new object[] { are };
                    ThreadPool.QueueUserWorkItem(Crash, procControl);
                    WaitHandle.WaitAll(waitHandles.ToArray());
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.Message);
            }
        }
    }
}

I naively thought that by having the try/catch I would be safe, but I found out the hard way that it is not the case (it is crashing one of my services).

like image 545
Otávio Décio Avatar asked Apr 22 '09 17:04

Otávio Décio


1 Answers

Well in general, you've no idea where the originating thread will be by the time the exception is thrown in the new thread - why would it be waiting around for the thread to throw an exception?

Think of the stacks involved - when an exception is thrown, it goes up the stack until it reaches an appropriate catch block. The new thread has a completely separate stack to the creating thread, so it'll never reach the catch block in the creating thread's stack.

EDIT: Of course, you could design your system so that the creating thread did wait for other things to happen - a bit like the message loop in a Windows Forms application. The new thread could then catch the exception and send a message to the creating thread, which could then deal with the exception. That isn't the normal setup though - you have to do it all explicitly.

like image 157
Jon Skeet Avatar answered Sep 18 '22 08:09

Jon Skeet