【问题标题】:Run BackgroundWorker after another one completed在另一个完成后运行 BackgroundWorker
【发布时间】:2012-01-02 16:34:31
【问题描述】:

我想在另一个完成后开始一个BackgroundWorker。我不确定如何为其编写代码,所以我真的没有什么可展示的。

我曾考虑将其写在 RunWorkerCompleted 中,但这似乎是为启动另一个工人设置逻辑的错误位置。

我应该在哪里以及如何做到这一点?

基本上,我想使用同一个工人,但要做其他事情。与第 1 步一样,它从文件中解析数据,在第 2 步中,在第 1 步完成后,它应该将解析后的数据从内存写入数据库。

【问题讨论】:

  • 启动另一个 BGW 没有意义。只需在第 1 步完成后让第一个也执行第 2 步代码即可。你甚至可以直接调用它的 DoWork() 方法。

标签: c# backgroundworker multithreading


【解决方案1】:

您可以改用 .NET 4.0 Task 类,然后使用 Task.ContinueWith 排队更多工作。

【讨论】:

  • 不幸的是,我在运行应用程序的机器上只有 .NET-3.5...
【解决方案2】:

最好使用两个不同的BackgroundWorker 组件。在第一个事件处理程序的RunWorkerCompleted 事件处理程序中启动第二个。这似乎是一种非常合理的做事方式。只是不要尝试使用单个BackgroundWorker

作为Tudor mentioned,您可以使用Task,但随后您将失去BackgroundWorker 的便利性,它具有熟悉的面向事件的界面、进度报告等。

【讨论】:

    【解决方案3】:

    根据您的描述,这些步骤似乎是相关的和连续的,因此我将其实现为单个 BGW,其中DoWork 在解析步骤和写入数据库步骤之间调用ReportProgress 执行这两个步骤.

    然后,您可以处理在 UI 线程上运行的 ProgressChanged 事件,以在解析步骤完成后执行任何逻辑,因为您知道工作人员已经在写入数据库。

    ReportProgress 接受一个整数来标识后台任务的完成百分比和一个可选的自定义对象。因此,在您的 ProgressChanged 处理程序中,您需要有逻辑来解释此进度信息。在这种情况下,作为一个两步工作,您只需致电ReportProgress(50)

    【讨论】:

    • ReportProgress 不仅接受整数。接受对象的重载有助于提供丰富的反馈。
    • 你说得对,我检查了 MSDN 并完全错过了过载。答案已更新。
    【解决方案4】:

    如果您可以接受使用第三方库进行作业调度,请查看 Quartz.NET 以及此处描述的作业侦听器机制 http://quartznet.sourceforge.net/tutorial/lesson_7.html。如果您想自己实现它,我会使用单个BackgroundWorker 来执行一组组织成责任链 的作业,您可以在http://dofactory.com/Patterns/PatternChain.aspx 阅读有关此模式的更多信息。

    【讨论】:

      【解决方案5】:

      这将允许使用一个后台工作人员进行多个和连续的操作:

          private void DoBackgroundWork<T>(string name, Func<T> work, Action<T> onComplete)
          {
              lblCurrentOperation.Text = name;
              StaticClass.OnProgress = (p) => backgroundWorker1.ReportProgress(p);
              T result = default(T);
              var handler = new DoWorkEventHandler((s, e) =>
              {
                  result = work();
              });
              backgroundWorker1.DoWork += handler;
      
              RunWorkerCompletedEventHandler completedHandler = null;
              completedHandler = new RunWorkerCompletedEventHandler((s, e) =>
              {
                  onComplete(result);
                  backgroundWorker1.DoWork -= handler;
                  backgroundWorker1.RunWorkerCompleted -= completedHandler;
                  lblCurrentOperation.Text = string.Empty;
                  progressBar1.Value = 0;
              });
              backgroundWorker1.RunWorkerCompleted += completedHandler;
          }
      

      用法:

                  DoBackgroundWork("Loading resources",
                  () =>
                  {
                      return DoWork();
                  },
                  (result) =>
                  {
                      //final UI operations
                      Task.Delay(500).ContinueWith(t => this.Invoke((Delegate)new Action(() => anotherOperationWithSameWorker())));
                  });
              backgroundWorker1.RunWorkerAsync();
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2014-09-28
        • 1970-01-01
        • 2014-10-11
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2019-11-20
        相关资源
        最近更新 更多