【问题标题】:Do I need to implement a background worker我需要实现一个后台工作者吗
【发布时间】:2012-03-14 02:25:23
【问题描述】:

我有一个主要的 GUI 应用程序,它在引用的程序集中完成所有实际工作。现在,我不在后台工作人员中做这项工作,所以它在处理时基本上锁定了主 UI。在我引用的组件中,我添加了很多事件来将不同的进度报告回主 UI 表单。在主 UI 表单上,我使用这些事件的值更新不同的文本框。我的问题是,首先,抛出这些事件时处理似乎要慢得多。那么我应该在辅助线程(来自引用的程序集)上触发事件吗?我对引用(静态)程序集的原始调用是否应该通过后台工作人员进行?我想在单独的线程上报告不同类型的进度,只是不确定采用哪种方法可以获得最佳性能。

谢谢

【问题讨论】:

    标签: c# multithreading backgroundworker


    【解决方案1】:

    从您的描述看来,您将从多线程中受益,因为它有助于保持 UI 响应。

    最简单的方法是使用 BackgroundWorker。从one of the many samples 开始工作,然后咬紧牙关,如果您有任何问题,请回到这里。

    回应评论:

    BackgroundWorker 工作线程与主线程通信的最佳方式是调用BackgroundWorker.ReportProgress 方法,该方法采用可选对象参数userState,您可以使用它来打包您要通信的数据。

    这会导致在主线程上引发 BackgroundWorker.ProgressChanged 事件 - 无需显式 Invoke 即可处理数据。

    如果您已经实现了事件,那么您要么必须重新调用ReportProgress 而不是引发事件,要么实现某种适配器来处理事件并将它们路由到ReportProgress 方法调用。

    【讨论】:

    • 感谢@Joe,我对 BackgroundWorker 或多线程没有任何问题,但我想我更好奇的是,如果引用的程序集职责是通过 BackgroundWorker 启动的,并且它们触发的静态事件是从 BackgroundWorker 的线程中触发,调用表单是在主 UI 线程上接收它们,还是在 Background 线程上接收它们?
    【解决方案2】:

    您可以在不同的线程上启动您的进程(另一个程序集上的方法),并在主窗体上处理由它引发的事件。

    由于 UI 不能被另一个线程更新,您应该将这些事件的代码包装在 this.Invoke() 中。

    例如:

    private void TheEventRaisedOnAnotherThread(object sender, EventArgs e)
    {
        _counter++;
        this.Invoke(new MethodInvoker(delegate() { TextBox1.Text = _counter.ToString(); }));
    }
    

    【讨论】:

    • 感谢@matap,所以我只是设置了一个辅助线程来调用我的“ReferencedAssembly.Go()”方法。那么 ReferencedAssembly 类引发的事件将通过主 UI 线程接收,对吗?辅助线程又名 BackgroundWorker
    • 如果在新线程上调用 ReferencedAssembly.Go,它的事件将在新线程上执行,而不是在主 UI 线程上执行。所以这就是为什么你应该使用 this.Invoke() 更新你的 UI。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-10-07
    • 2011-07-29
    相关资源
    最近更新 更多