views:

135

answers:

5

How to catch exception in the main thread if the exception occurs in the secondary thread?

The code snippet for the scenario is given below:

private void button1_Click(object sender, EventArgs e)
{
    try
    {
        Thread th1 = new Thread(new ThreadStart(Test));
        th1.Start();               
    }
    catch (Exception)
    { 

    }
}

void Test()
{
    for (int i = 0; i < 100; i++)
    {
        Thread.Sleep(100);

        if (i == 2)
            throw new MyException();
    }
}
+3  A: 

You can add a Application.ThreadException Event handler:

Joe is correct. Given the above windows forms code I was assuming Windows forms:

This event allows your Windows Forms application to handle otherwise unhandled exceptions that occur in Windows Forms threads. Attach your event handlers to the ThreadException event to deal with these exceptions, which will leave your application in an unknown state. Where possible, exceptions should be handled by a structured exception handling block.

See Unexpected Errors in Managed Applications

Mitch Wheat
I think this answer is wrong. AFAIK (but I don't have time to test it), Application.ThreadException only handles exceptions from the UI thread (e.g. an unhandled exception in an event handler for a WinForms control). Exceptions from worker threads can be handled by an AppDomain.UnhandledException event handler, but the handler will run on the worker thread, not the main UI thread. If you want to handle exceptions from a worker thread on a WinForms UI thread, the best solution is to use a BackgroundWorker as indicated in my answer.
Joe
@Mitch: that could be ASP.NET code as easily as Windows Forms. It could even be pseudo-code.
John Saunders
True. I'm currently working on Winforms, so everything looks like winforms!
Mitch Wheat
+2  A: 

Use a BackgroundWorker.

A BackgroundWorker provides the infrastructure for communicating between the main UI thread and a background worker thread, including reporting exceptions. It is almost always a better solution than starting a thread from a button_click event handler.

Joe
@Joe ??????????
Lirik
" ??????????" - A BackgroundWorker provides the infrastructure for communicating between the main UI thread and a background worker thread, including reporting exceptions. It is almost always a better solution than starting a thread from a button_click event handler like the OP's sample.
Joe
@Joe, sure... so put it in your answer :). Not that a reference is bad, but an explanation is even better!
Lirik
A: 

You might also use an asynchronous delegate to bubble up the information if you're concerned about globally trapping all exceptions.

see here

That is to say, trap the exception in thread B and use the Async Delegate to bubble information up to thread A. That way can can specifically target when the data from the exception is handled.

Laramie
A: 

As @codeka said, you can't. But if you want to do some UI stuff (May be displaying an error MessageBox to the user) in catch block in secondary thread, you can enclose like this. Better if you use BackgroundWorker

Invoke(new Action(() =>
{
  MessageBox.Show("Message");
}));
Ismail
+1  A: 

You should consider adding your exception handling in your test method and deal with exceptions there.

The free Threading in C# ebook discusses this approach (and some others). Scroll down to the 'Exception Handling' section.

Jay Riggs