简体   繁体   English

如果在辅助线程中发生异常,如何在主线程中捕获异常?

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

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

You can add a Application.ThreadException Event handler: 您可以添加Application.ThreadException事件处理程序:

Joe is correct. 乔是对的。 Given the above windows forms code I was assuming Windows forms: 鉴于上面的Windows窗体代码我假设Windows窗体:

This event allows your Windows Forms application to handle otherwise unhandled exceptions that occur in Windows Forms threads. 此事件允许Windows窗体应用程序处理Windows窗体线程中出现的其他未处理的异常。 Attach your event handlers to the ThreadException event to deal with these exceptions, which will leave your application in an unknown state. 将事件处理程序附加到ThreadException事件以处理这些异常,这将使您的应用程序处于未知状态。 Where possible, exceptions should be handled by a structured exception handling block. 在可能的情况下,异常应由结构化异常处理块处理。

See Unexpected Errors in Managed Applications 请参阅托管应用程序中的意外错误

Use a BackgroundWorker . 使用BackgroundWorker

A BackgroundWorker provides the infrastructure for communicating between the main UI thread and a background worker thread, including reporting exceptions. BackgroundWorker提供用于在主UI线程和后台工作线程之间进行通信的基础结构,包括报告异常。 It is almost always a better solution than starting a thread from a button_click event handler. 它几乎总是比从button_click事件处理程序启动线程更好的解决方案。

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). C#电子书中的免费线程讨论了这种方法(以及其他一些方法)。 Scroll down to the 'Exception Handling' section. 向下滚动到“异常处理”部分。

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. 也就是说,在线程B中捕获异常并使用Async Delegate将信息冒泡到线程A.这种方式可以专门针对处理异常数据的时间。

As @codeka said, you can't. 正如@codeka所说,你做不到。 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. 但是如果你想在辅助线程的catch块中做一些UI东西(可能会向用户显示错误MessageBox),你可以这样包围。 Better if you use BackgroundWorker 如果您使用BackgroundWorker,那就更好了

Invoke(new Action(() =>
{
  MessageBox.Show("Message");
}));

You can (now…this wasn't available when the question was originally asked) use async and await : 您可以(现在......在最初询问问题时无法使用)使用asyncawait

private async void button1_Click(object sender, EventArgs e)
{
    try
    {
        await Task.Run(Test);
    }
    catch (Exception)
    { 

    }
}

The Task.Run() method will cause the Test() method to be executed in a worker thread. Task.Run()方法将导致Test()方法在工作线程中执行。 If an unhandled exception is thrown in that thread, the Task will propagate that exception back to the awaiting thread at the await statement. 如果在该线程中抛出未处理的异常,则Task会将该异常传播回await语句中的等待线程。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM