【问题标题】:Background worker doesn't catch errors from ThreadPool后台工作人员不会从 ThreadPool 中捕获错误
【发布时间】:2014-06-19 11:13:05
【问题描述】:

我正在使用 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),但没有成功。

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

【问题讨论】:

  • 为什么一个完全独立的线程(能够)将异常传递给 Bgw?
  • 只需使用(另一个)Bgw 或查看 Task 和 Parallel 类。裸(池)线程不进行异常转发。
  • 一些想法...您使用的是哪个版本的 .NET?如果您使用的是 .NET 4 或更早版本,那么肯定有更好的方法来做到这一点。重新考虑一下为什么会有后台工作人员的“DoWork”方法在 ThreadPool 上放置一些东西。您说您需要使用线程池进行异步工作,但这不是真的,BackgroundWorker 会为您执行此操作,但会在 ThreadPool 线程上调用您的“DoWork”方法...msdn.microsoft.com/en-us/library/h01xszh2(v=vs.110).aspx。您只需要调用未在代码中显示的 RunWorkerAsync。这就是使用 BackgroundWorker 的重点。

标签: c# multithreading exception-handling backgroundworker threadpool


【解决方案1】:

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

如果您尝试从后台工作人员启动更多 ThreadPool 任务,那么我想这可能是一个考虑因素,但在这种情况下,我建议尽可能在 .NET4 中使用 TPL...

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

如果您不能使用 TPL,那么您必须将 ThreadPool 代码包装在 TryCatch 中,并将异常放置在该方法之外可以访问的某个位置。

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

这本质上就是 TPL 为您所做的……为您提供一个“观察”后台线程上发生的异常的地方,但您仍然有责任在 Task.Exception 中查找这些异常属性,或者通过调用将为您重新抛出异常的方法。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-10-25
    • 1970-01-01
    • 2015-11-18
    • 1970-01-01
    • 2014-04-14
    相关资源
    最近更新 更多