2010-02-18 74 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