使用计时器测量 Parallel.ForEach 进度意外暂停

Using Timer to measure Parallel.ForEach progress pauses unexpectedly

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

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

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

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

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

您应该在单独的 thread/backgroundworker/task 上使用它来更新您的进度变量,同时不阻塞 UI。

如果您从 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 线程,以便在处理过程中处理进度更新。