возвращая ноль с PLINQ - PullRequest
       5

возвращая ноль с PLINQ

7 голосов
/ 19 февраля 2010

У меня есть метод расширения для IEnumerable, который затем перебирает коллекцию, выполняет свою работу, а затем возвращает новый IEnumerable.

Я пытался использовать PLINQ, используя .AsParallel (). ForAll (), который значительно ускоряет итерации (что, конечно, должно быть), однако, когда коллекция возвращается, в этой коллекции часто есть несколько объектов, которые нуль.

Я предполагаю, что это может быть потому, что он возвращает коллекцию до того, как у всех "бизнесов" есть шанс завершить? если я отлаживаю и ставлю точку останова, нулей нет.

Есть ли какой-нибудь метод "ожидания завершения этой операции", который я должен использовать?

РЕДАКТИРОВАТЬ: , чтобы быть немного яснее, в конечном итоге есть бизнес-логика, изменение свойств и т. Д. Необходимо иметь зацикленное действие, а не просто выбрать что-то.

Ответы [ 2 ]

1 голос
/ 19 февраля 2010

Ответ зависит от того, что вы подразумеваете под возвращением , потому что метод 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 */);

В этом случае делегат просто возвращает результат. Метод Where собирает все результаты, и когда вы перебираете возвращенный IEnumerable, он гарантирует, что все делегаты закончили вычисления.

0 голосов
/ 19 февраля 2010

ForAll() не выполняет слияние и возвращает немедленно.Parallel.ForEach() - это, вероятно, та функция, которую вы ищете.

т.е. вместо:

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

что-то вроде

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

...