【问题标题】:Using Timer to measure Parallel.ForEach progress pauses unexpectedly使用 Timer 测量 Parallel.ForEach 进度意外暂停
【发布时间】:2015-01-31 03:43:02
【问题描述】:

我第一次使用Parallel.ForEach,我正在处理文件;在 WinForms 应用程序的上下文中。

根据其他线程关于此编码问题的指导(Parallel.ForEach 进度报告),我的类上有一个公共 (int) 计数器属性,其中包含并行代码,并且它正在成功更新;我的表单上还有一个计时器,它会定期读取计数器。

问题是当我执行并行代码时,可见的进度更新似乎停止了,然后在并行代码完成后立即开始。

仅供参考 - 我直接调用并行代码 - 也就是说,不是通过后台工作程序或异步方法。

【问题讨论】:

    标签: c# winforms timer parallel.foreach


    【解决方案1】:

    Parallel.ForEach 实际上以并行方式评估查询,但确实等待执行完成并阻塞调用线程。

    您应该在单独的线程/后台工作人员/任务上使用它,以在不阻塞 UI 的情况下更新您的进度变量。

    【讨论】:

      【解决方案2】:

      如果您从 UI 线程调用 Parallel.ForEach()(缺少代码示例,我们无法确定发生了什么),那么该方法停止并等待所有处理完成的事实将阻止您的 UI 线程不会做任何其他工作,包括 a) 允许处理计时器事件,以及 b) 即使处理了计时器,也允许更新 UI。

      一种可能的方法是将Parallel.ForEach() 的调用封装在对Task.Run() 的调用中。例如:

      private async void button1_Click(object sender, EventArgs e)
      {
          // some stuff
      
          await Task.Run(() => Parallel.ForEach(...));
      
          // some other stuff
      }
      

      或者,您可以将整个事情作为单独的任务执行:

      private async void button1_Click(object sender, EventArgs e)
      {
          // some stuff
      
          List<Task> tasks = new List<Task>();
      
          foreach (...)
          {
              tasks.Add(Task.Run(() => ...));
          }
      
          await Task.WhenAll(tasks);
      
          // some other stuff
      }
      

      (以上示例省略了细节,因为问题中没有代码示例,就无法知道实际会出现什么)。

      这两种方法都应该释放您的 UI 线程,以便在处理进行时处理进度更新。

      【讨论】:

      • 干杯 Peter 和 Yorye,让我按照这些思路工作。
      • 谢谢,我已经使用异步方法和等待(类似于您的第一个代码块)。我会看看情况如何,并根据需要进行重构。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2019-12-07
      • 1970-01-01
      • 2013-03-04
      • 2011-04-21
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多