6

I have thread Like this, after i see example link text

ThreadStart _threadStart = new ThreadStart(delegate()
{
       try
       {
           threadFunction(httpContext);
       }
       catch (Exception ex)
       {
           throw ex;
       }
 });
 Thread _thread = new Thread(_threadStart);
  _thread.Start();

when an Exception happen it dosen't re-thrown in the thread that started it. So what i'm doing wrong or how to do it?

Note: thanks to all comments in advanced

Community
  • 1
  • 1
Hiyasat
  • 8,601
  • 7
  • 33
  • 59
  • 6
    Note you should *never* rethrow an exception like you do there. Just doing `throw;` in the catch block suffices ... – Joey Jan 23 '11 at 13:09
  • i know bu i throw custom exception inherited from "System.Exception" with message – Hiyasat Jan 23 '11 at 13:23
  • 1
    You have to throw a *new* exception with the info you want to add. Pass the *original* exception as the InnerException. Do this only if the added info is of high value since it makes troubleshooting more difficult. – Hans Passant Jan 23 '11 at 14:51

6 Answers6

8

The exception will be thrown, but that will only end the thread. The exception isn't re-thrown in the thread that started it.

Guffa
  • 687,336
  • 108
  • 737
  • 1,005
  • Why is that? and what is the best solution to do it? – Hiyasat Jan 23 '11 at 13:21
  • 1
    @Hiyasat: If a thread could throw any exception in it's starting thread at any time, it would be very hard to implement the starting thread to handle that. You have to communicate the exception back to the starting thread just like you send back any other result, for example using a varaible that both threads have access to. – Guffa Jan 23 '11 at 14:25
6

I think the heart of the matter is to understand that exceptions that occur within a thread will not be passed to the calling thread for handling.

For example, say you have a rebel method:

private static void RebelWithoutACause()
{
    throw new NullReferenceException("Can't touch this!");
}

Let's say you create a new thread that calls this method in your program, and being a safe programmer, you decide to envelope the work in a try/catch block:

private static void Main(string[] args)
{
    try
    {
        var thread = new Thread(RebelWithoutACause);
        thread.Start();
        thread.Join();
    }
    catch (Exception ex)
    {
        Console.WriteLine(ex.ToString());
    }
}

However, if you run this in the debugger, you will find out that you'll never get to the catch block, and instead the thread will be killed, and the debugger will complain that you have an unhandled exception.

You need to take your pick of how to handle the exceptions, but the handling needs to happen inside each thread entry method. Typical handling includes logging the details, notifying users via the UI, and shutting down your application as gracefully as you can.

Gustavo Mori
  • 8,319
  • 3
  • 38
  • 52
2

Are you sure that the exception is thrown? If a thread fails with an exception, the whole application will crash, which you can notice using the AppDomain.CurrentDomain.UnhandledException event (note that by the time the event has fired, you cannot prevent your application from being ended, but can clean-up resources and save critical data - see the event documentation for more information).

But, to quote the accepted answer from the thread you referred to:

Any thread that raises a top-level exception indicates a big problem.

You should try logging the exception, and/or signaling the other thread(s) that this thread has failed.

Community
  • 1
  • 1
ShdNx
  • 3,172
  • 5
  • 40
  • 47
1

The exception is being thrown, except I guess you do not see it, since it is thrown on another thread. Therefore, the UI thread (or whatever thread invoked the other thread), cannot catch the exception, since it doesn't see it.

If you log the exception to a file for instance, I'm sure you'll see it. :)

Frederik Gheysels
  • 56,135
  • 11
  • 101
  • 154
0

maybe do something like this:

   const int numThreads = 8;
   Thread[] threads = new Thread[numThreads];
   Exception[] threadsExceptions = new Exception[numThreads];
   for (int i = 0; i < numThreads; i++) {
       threadsExceptions[i] = null;
       int closureVariableValue = i;
       ThreadStart command = () =>
       {
           try
           {
               throw new ArgumentException("thread_" + closureVariableValue + "'s exception");
           }catch(Exception any)
           {
               threadsExceptions[closureVariableValue] = any;
           }
       };
       threads[i] = new Thread(command);
       threads[i].Start();
   }
   for(int i = 0; i < numThreads; i++)
   {
       threads[i].Join();
       if (threadsExceptions[i] != null)
       {
           throw threadsExceptions[i];
       }
   }
Austin_Anderson
  • 900
  • 6
  • 16
0

I think perhaps you should look at using the BackgroundWorker class. You can subscribe to the RunWorkerCompleted event, and it has an Error property that will contain your exception.

antsyawn
  • 971
  • 10
  • 17
  • Thanks, but i found something more powerful in .NET 4 Task http://blogs.msdn.com/b/pfxteam/archive/2009/05/31/9674669.aspx – Hiyasat Jan 25 '11 at 07:38
  • Thanks for the link - Tasks look great, I haven't had a chance to check them out yet. – antsyawn Jan 31 '11 at 22:08