views:

2674

answers:

4

I have a method running in a seperate thread. The thread is created and started from a form in a windows application. If an exception is thrown from inside the thread, what is the best way to pass it back to the main application. Right now, I'm passing a reference to the main form into the thread, then invoking the method from the thread, and causing the method to be called by the main application thread. Is there a best practice way to do this because I'm not comfortable with how I'm doing it now.

Example of my form:

public class frmMyForm : System.Windows.Forms.Form
{
    /// <summary>
    /// Create a thread
    /// </summary>
    /// <param name="sender"></param>
    /// <param name="e"></param>
    private void btnTest_Click(object sender, EventArgs e)
    {
        try
        {
            //Create and start the thread
           ThreadExample pThreadExample = new ThreadExample(this);
           pThreadExample.Start();
        }
        catch (Exception ex)
        {
            MessageBox.Show(ex.Message, Application.ProductName);
        }
    }

    /// <summary>
    /// Called from inside the thread 
    /// </summary>
    /// <param name="ex"></param>
    public void HandleError(Exception ex)
    {
        //Invoke a method in the GUI's main thread
        this.Invoke(new ThreadExample.delThreadSafeTriggerScript(HandleError), new Object[] { ex });
    }

    private void __HandleError(Exception ex)
    {
        MessageBox.Show(ex.Message);
    }
}

Example of my thread class:

public class ThreadExample
{
    public delegate void delThreadSafeHandleException(System.Exception ex);

    private Thread thExample_m;

    frmMyForm pForm_m;
    private frmMyForm Form
    {
        get
        {
            return pForm_m;
        }
    }

    public ThreadExample(frmMyForm pForm)
    {
        pForm_m = pForm;

        thExample_m = new Thread(new ThreadStart(Main));
        thExample_m.Name = "Example Thread";
    }

    public void Start()
    {
        thExample_m.Start();
    }

    private void Main()
    {
        try
        {
            throw new Exception("Test");
        }
        catch (Exception ex)
        {
            Form.HandleException(ex);
        }
    }
}
+1  A: 

Throwing exceptions between threads is not easy and probably not desired. instead you can pass the exception using a shared data structure or variable and use waitHandle to wait on the 1st thread.

Dror Helper
+1  A: 

So you're using Invoke to marshall back to the UI thread, by the looks of it - which is exactly what you need to do. I'd personally use an Action<Exception> for simplicity's sake, and possibly BeginInvoke instead of Invoke, but basically you're doing the right thing.

Jon Skeet
Thanks, I've never used Action<T> before. Good suggestion.
Jeremy
+1  A: 

Probably a better way would be to pass a delegate into the thread instead of a reference to the form itself.

awhite
A: 

Use the BackgroundWorker class in the .NET framework instead. It is the best practice for performing UI work on a different thread.

jezell