C# 从另一个线程捕获异常

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/188977/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-03 17:20:04  来源:igfitidea点击:

catching exceptions from another thread

c#.netmultithreadingexceptionexception-handling

提问by Jeremy

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.

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

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

采纳答案by Jon Skeet

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.

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

回答by Dror Helper

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.

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

回答by Jon Skeet

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

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

回答by jezell

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

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

回答by Mrinmoy Das

I totally agree with Dror. In a formal way we can call this structure as FaultContract. Fundamentally when an exception has happened in another thread, the client thread can hardly do any thing at that moment except that to collect that information and act accordingly in it's own theread. If the thereads are in different AppPool then there is an extra complexity of Serialization (that can be a seperate topic altogether).

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