Parallel.ForEach () vs. foreach (IEnumerable <T> .AsParallel ())

143

Erg, estou tentando encontrar esses dois métodos na BCL usando o Reflector, mas não consigo localizá-los. Qual é a diferença entre esses dois trechos?

UMA:

IEnumerable<string> items = ...

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

B:

IEnumerable<string> items = ...

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

Existem consequências diferentes do uso de um sobre o outro? (Suponha que tudo o que estou fazendo nos corpos entre colchetes dos dois exemplos seja seguro para threads.)

SnickersAreMyFave
fonte

Respostas:

148

Eles fazem algo bem diferente.

O primeiro pega o delegado anônimo e executa vários threads nesse código em paralelo para todos os itens diferentes.

O segundo não é muito útil nesse cenário. Em poucas palavras, pretende-se fazer uma consulta em vários threads, combinar o resultado e devolvê-lo ao thread de chamada. Portanto, o código na instrução foreach permanece sempre no thread da interface do usuário.

Só faz sentido se você fizer algo caro na consulta linq à direita da AsParallel()chamada, como:

 var fibonacciNumbers = numbers.AsParallel().Select(n => ComputeFibonacci(n));
svick
fonte
Qual é o benefício de simplesmente fazer um foreach paralelo no computefibonacci?
l
51

A diferença é que B não é paralelo. A única coisa que AsParallel()faz é envolver um a IEnumerable, para que, quando você use os métodos LINQ, suas variantes paralelas sejam usadas. O invólucro GetEnumerator()(que é usado nos bastidores no foreach) até retorna o resultado da coleção original GetEnumerator().

BTW, se você quiser examinar os métodos no Refletor, AsParallel()está na System.Linq.ParallelEnumerableclasse na System.Coremontagem. Parallel.ForEach()está na mscorlibmontagem (espaço para nome System.Threading.Tasks).

svick
fonte
O que você quer dizer com ... Suas variantes paralelas são usadas ...?
l
2
@ pontuação Isso, por exemplo, quando você escreve .Select(), chama ParallelEnumerable.Select()e não o normal Enumerable.Select().
svick
50

O segundo método não será paralelo, a maneira correta de usar AsParallel () no seu exemplo seria

IEnumerable<string> items = ...

items.AsParallel().ForAll(item =>
{
    //Do parallel stuff here
});
Scott Chamberlain
fonte
3
Por que usar a combinação de asparalela e forall em vez de simplesmente foreach?
l