Parallel.ForEach () против foreach (IEnumerable ‹T› .AsParallel ())

Эрг, я пытаюсь найти эти два метода в BCL с помощью Reflector, но не могу их найти. В чем разница между этими двумя фрагментами?

A:

IEnumerable<string> items = ...

Parallel.ForEach(items, item => {
   ...
});

B:

IEnumerable<string> items = ...

foreach (var item in items.AsParallel())
{
   ...
}

Есть ли разные последствия использования одного по сравнению с другим? (Предположим, что все, что я делаю в заключенных в скобки текстах обоих примеров, является потокобезопасным.)


person SnickersAreMyFave    schedule 24.09.2010    source источник


Ответы (3)


Они делают совсем другое.

Первый принимает анонимного делегата и запускает несколько потоков в этом коде параллельно для всех различных элементов.

Второй не очень полезен в этом сценарии. Вкратце, он предназначен для выполнения запроса в нескольких потоках, объединения результатов и их повторной передачи вызывающему потоку. Таким образом, код оператора foreach всегда остается в потоке пользовательского интерфейса.

Это имеет смысл только в том случае, если вы делаете что-то дорогое в запросе linq справа от вызова AsParallel(), например:

 var fibonacciNumbers = numbers.AsParallel().Select(n => ComputeFibonacci(n));
person Community    schedule 24.09.2010
comment
В чем преимущество простого параллельного выполнения foreach для computefibonacci? - person Alex Gordon; 15.02.2017

Второй метод не будет параллельным, правильный способ использования AsParallel () в вашем примере будет

IEnumerable<string> items = ...

items.AsParallel().ForAll(item =>
{
    //Do parallel stuff here
});
person Scott Chamberlain    schedule 24.09.2010
comment
Зачем использовать комбинацию asparallel вместе с forall вместо простого foreach? - person Alex Gordon; 15.02.2017

Разница в том, что B не параллельна. Единственное, что делает AsParallel(), это то, что он оборачивается вокруг IEnumerable, так что при использовании методов LINQ используются их параллельные варианты. GetEnumerator() оболочки (которая используется за кулисами в foreach) даже возвращает результат GetEnumerator() исходной коллекции.

Кстати, если вы хотите взглянуть на методы в Reflector, AsParallel() находится в классе System.Linq.ParallelEnumerable сборки System.Core. Parallel.ForEach() находится в сборке mscorlib (пространство имен System.Threading.Tasks).

person svick    schedule 24.09.2010
comment
Что вы имеете в виду под ... Используются их параллельные варианты ...? - person Alex Gordon; 15.02.2017
comment
@punctuation Это, например, когда вы пишете .Select(), он вызывает ParallelEnumerable.Select(), а не обычный Enumerable.Select(). - person svick; 16.02.2017