0

我有一个包含 100K 项目的并发集合。集合中每个项目的处理时间可能短至 100 毫秒,也可能长达 10 秒。我想通过并行处理来加快速度,并让 100 个仆从同时完成这项工作。当此处理发生时,我还必须向 UI 报告一些特定数据,而不仅仅是完成百分比。

我希望并行化的子任务蚕食并发集合,就像一群小鱼攻击扔进池塘的一块面包。如何将并发集合公开给并行任务?我可以有一个正常的循环并简单地在循环内启动一个异步任务并传递一个 IProgress 吗?我什至需要并发收集吗?

有人建议我使用 Parallel.ForEach 但我看不到由并行度建立的每个子进程如何将自定义对象及其处理的每个项目报告回 UI,不仅在它完成之后处理其在 100K 项目中的份额。

4

1 回答 1

0

该框架已经为此目的提供了IProgress接口,并提供了一个正在进行中的实现。要报告进度,请使用进度值调用IProgress.Report。值 T 可以是任何类型,而不仅仅是数字。

每个 IProgress 实现都可以以自己的方式工作。Progress 引发一个事件并调用您在创建它时传递给它的回调。

此外,Progress.Report 异步执行。在幕后,它使用SychronizationContext.Post在创建 Progress 实例的线程上执行其回调和所有事件处理程序。

假设您创建了一个这样的进度值类:

class ProgressValue
{
    public long Step{get;set;}
    public string Message {get;set;}
}

你可以这样写:

IProgress<ProgressValue> myProgress=new Progress<ProgressValue>(p=>
{
    myProgressBar.Value=p.Step;
});

IList<int> myVeryLargeList=...;
Parallel.ForEach(myVeryLargeList,item,state,step=>
{
    //Do some heavy work
    myProgress.Report(new ProgressValue
    {
         Step=step,
         Message=String.Format("Processed step {0}",step);
    });
});

编辑

哎呀!Progress 显式地实现了 IProgress。正如@Tim 所注意到的,您必须将其转换为 IProgress 。

修复了将 myProgress 显式声明为 IProgress 的代码。

于 2013-08-02T11:06:40.973 回答