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

时间:2014-05-02 17:27:04

标签: c# multithreading exception-handling backgroundworker threadpool

我正在使用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),但它不起作用。

希望你能帮助我。 提前谢谢。

1 个答案:

答案 0 :(得分:0)

您不需要从DoWork方法将代码放在ThreadPool上。当您致电_bgWorker_DoWork时,BackgroundWorker将自动在ThreadPool线程上引发RunWorkerAsync()方法。

如果你试图从你的后台工作者那里开始几个更多的ThreadPool任务,那么我想这可能是一个考虑因素,但在这种情况下我会建议在.NET4中使用TPL,如果可能的话......

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

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

例如,在您的UI类中添加internal static List<Exception> backgroundExceptions;成员,后台工作者添加此列表中的任何捕获的异常,然后您必须在后台工作完成后调查此列表,以查看是否存在任何异常

这基本上就是TPL正在为你做的事情......给你一个“观察”后台线程上发生的异常的地方,但你仍然有责任在{{1}中寻找那些例外。通过调用将为您重新抛出异常的方法。