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

143

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

A:

IEnumerable<string> items = ...

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

B:

IEnumerable<string> items = ...

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

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

SnickersAreMyFave
источник

Ответы:

148

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

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

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

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

 var fibonacciNumbers = numbers.AsParallel().Select(n => ComputeFibonacci(n));
svick
источник
Какая польза от простого параллельного foreach на computefibonacci?
l -''''''--------- '' '' '' '' '' ''
51

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

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

svick
источник
Что вы подразумеваете под ... Их параллельные варианты используются ...?
l --''''''--------- '' '' '' '' '' ''
2
@punctuation Что, например, когда пишешь .Select(), звонит ParallelEnumerable.Select()и не нормально Enumerable.Select().
svick
50

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

IEnumerable<string> items = ...

items.AsParallel().ForAll(item =>
{
    //Do parallel stuff here
});
Скотт Чемберлен
источник
3
Зачем использовать комбинацию asparallel вместе с forall вместо просто foreach?
l -''''''--------- '' '' '' '' '' ''