后台工作线程不会从ThreadPool捕获错误

本文关键字:ThreadPool 错误 工作 线程 后台 | 更新日期: 2023-09-27 18:01:36

我使用BackgroundWorker,因为我需要在我的UI中给出反馈。我还需要在我的类中使用ThreadPool来异步运行,但似乎我的后台工作人员无法捕获它抛出的异常。

它的目的是给出一个关于它正在做什么任务的反馈。

我做了一个简单的应用程序,它再现了这个问题:

    // MAIN UI CLASS
    BackgroundWorker _bgWorker = new BackgroundWorker();
    void _bgWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
    {
        if (e.Error != null)
        {
            // Returns custom error
            MessageBox.Show(e.Error.Message);
        }
    }
    void _bgWorker_DoWork(object sender, DoWorkEventArgs e)
    {
         try {
            // Initialize test error class
            var testClass = new TestClass();
         }
         catch (Exception ex)
         {
             MessageBox.Show("im from trycatch");
         }

    }
    private void Window_ContentRendered(object sender, EventArgs e)
    {
        _bgWorker.DoWork += _bgWorker_DoWork;
        _bgWorker.RunWorkerCompleted += _bgWorker_RunWorkerCompleted;
    }
    /////////////////////////////////////////////////////////////////////////
    // TEST ERROR CLASS
    public TestClass()
    {
        throw new Exception("im a custom error");
    }

可以正常工作。使用try-catch,它捕获由try-catch处理的错误。然而,没有try-catch,它在RunWorkerCompleted中处理它。

然而,我真的需要异步地做这些方法(这就是为什么我使用ThreadPool),但是调试器总是指向异常(只有当我在没有调试器的情况下尝试它时才会崩溃)

    // TEST ERROR CLASS
    public TestClass()
    {
        ThreadPool.QueueUserWorkItem(delegate
        {
             throw new Exception("im a custom error");
        }
    }

我尝试使用try-catch语句重新抛出错误(希望它将异常传递给BackgroundWorker),但它没有工作。

希望你能帮助我。

后台工作线程不会从ThreadPool捕获错误

您不需要从DoWork方法中将代码放在ThreadPool上。当你调用RunWorkerAsync()时,BackgroundWorker会自动触发ThreadPool线程上的_bgWorker_DoWork方法。

如果你试图从后台工作器启动更多的线程池任务,那么我想这可能是一个考虑因素,但在这种情况下,我会建议在。net 4中使用TPL,如果可能的话…

http://msdn.microsoft.com/en-us/library/dd460717 (v = vs.110) . aspx

如果你不能使用TPL,那么你必须把你的ThreadPool代码包装在TryCatch中,并把异常放在可以在该方法之外访问的地方。

例如,在你的UI类中添加一个internal static List<Exception> backgroundExceptions;成员,后台工作器将任何捕获的异常添加到这个列表中,然后你必须在后台工作完成后调查这个列表,看看是否有任何异常存在。

这就是TPL为你所做的…给你一个地方"观察"发生在后台线程的异常,但它仍然是你的责任去寻找这些异常,无论是在Task.Exception属性,或通过调用一个方法,将重新抛出异常为你。