2010-02-18 80 views
7

我有一个IEnumerable的扩展方法,然后遍历集合,做它的业务,然后返回一个新的IEnumerable。返回null与PLINQ

我试图使用PLINQ .AsParallel()。ForAll()显着加速迭代(当然它应该这样做),但是当收集返回时,该集合中经常有一些对象为空。

我假设这可能是因为它是在所有'业务'有机会完成之前返回集合?如果我调试并放入断点,则没有空值。

是否有某种'等待此操作完成'的方法,我应该使用?

编辑:要更清楚一点,有业务逻辑的所有,修改属性等,有必要有一个动作循环,而不是简单地选择一些东西。

+0

你能告诉我们一个代码示例? – 2010-02-18 23:57:46

+0

ParallelEnumerable .ForAll()不会返回任何东西(void ForAll(...)),而不是IEnumerable - 如果您使用的是ForAll,则不会返回可枚举值...您需要显示码。 – 2010-02-19 00:02:43

+0

不好意思。该方法返回集合,而不是所有的。 – benpage 2010-02-19 00:55:37

回答

1

答案取决于你的意思是返回,因为ForAll方法不返回任何东西。它会并行地调用您为集合的所有元素指定的委托。我会想你的代码如下所示:

data.AsParallel().ForAll(() => /* calculate and store result somewhere */); 
// more code 

ForAll方法不会等待所有与会代表来完成的,所以more code能之前所有代表完全执行(你还需要在store result somewhere小心!一点,因为它可以为多种代表同时运行)

我觉得代码可以更优雅的使用方法Select被改写:

var res = data.AsParallel().Select(() => /* calculate the result */); 

在这种CAS e,代表只是返回结果。 Where方法收集所有结果,并且当您遍历返回的IEnumerable时,它确保所有代表完成计算。

+0

谢谢汤姆 - 抱歉含糊不清,该方法返回集合,它不能从forall返回 - 那里有太多的业务逻辑。 – benpage 2010-02-19 00:57:55

+0

在这种情况下,您需要非常小心,因为操作正在并发执行 - 您几乎肯定需要一些锁。 PLINQ最适用于具有“返回结果”(又称功能)而非“修改状态”(又名势在必行)的代码。 – 2010-02-19 01:30:28

0

ForAll()不执行合并,并立即返回。 Parallel.ForEach()可能是您正在寻找的功能。

即代替:

collection.AsParallel().ForAll(t=>t.doWork());

Parallel.ForEach(collection.AsParallel(), t=>t.doWork());

+0

嗯..不好 - Parallel.ForEach(collection,t => t.doWOrk());导致同样的问题,并且Parallel.ForEach(collection.AsParallel(),t => t.doWork());抛出一个聚合异常 – benpage 2010-02-19 01:39:49

+0

奇怪...''Parallel.ForEach()'返回一个'ParallelLoopResult',它有一个'IsCompleted'属性,你可以检查。不过,我会研究'AggregateException'的内容,也许在你的'doWork()'函数中没有正确的发生。 – Tanzelax 2010-02-19 02:09:17