it-roy-ru.com

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())
{
   ...
}

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

139
SnickersAreMyFave

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

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

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

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

 var fibonacciNumbers = numbers.AsParallel().Select(n => ComputeFibonacci(n));
147
user180326

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

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

49
svick

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

IEnumerable<string> items = ...

items.AsParallel().ForAll(item =>
{
    //Do parallel stuff here
});
48
Scott Chamberlain