13

我有一个在单独的线程中运行的方法。线程是从 Windows 应用程序中的窗体创建和启动的。如果从线程内部抛出异常,将其传递回主应用程序的最佳方法是什么。现在,我将对主窗体的引用传递到线程中,然后从线程中调用该方法,并导致该方法被主应用程序线程调用。是否有最佳实践方法来做到这一点,因为我对我现在的做法感到不舒服。

我的表格示例:

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);
    }
}

我的线程类的示例:

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);
        }
    }
}
4

5 回答 5

17

因此,从外观上看,您正在使用 Invoke 编组回 UI 线程 - 这正是您需要做的。为简单起见,我个人会使用 Action<Exception>,并且可能会使用 BeginInvoke 而不是 Invoke,但基本上你在做正确的事情。

于 2008-10-09T20:08:42.237 回答
5

请改用 .NET 框架中的 BackgroundWorker 类。这是在不同线程上执行 UI 工作的最佳实践。

于 2008-10-20T21:20:02.577 回答
2

可能更好的方法是将委托传递给线程而不是对表单本身的引用。

于 2008-10-09T20:09:48.880 回答
1

在线程之间抛出异常并不容易,也可能是不希望的。相反,您可以使用共享数据结构或变量传递异常,并使用 waitHandle 在第一个线程上等待。

于 2008-10-09T20:08:16.920 回答
0

我完全同意 Dror。在正式的方式中,我们可以将此结构称为 FaultContract。从根本上说,当另一个线程中发生异常时,客户端线程此时几乎不能做任何事情,除了收集该信息并在它自己的读取中采取相应的行动。如果 thereads 在不同的 AppPool 中,那么序列化会更加复杂(这可以完全是一个单独的主题)。

于 2012-08-16T11:10:45.050 回答