使用计时器测量 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 线程,以便在处理过程中处理进度更新。
我是第一次使用 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 线程,以便在处理过程中处理进度更新。