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

143

Erg, ich versuche, diese beiden Methoden mit Reflector in der BCL zu finden, kann sie aber nicht finden. Was ist der Unterschied zwischen diesen beiden Schnipsel?

EIN:

IEnumerable<string> items = ...

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

B:

IEnumerable<string> items = ...

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

Gibt es unterschiedliche Konsequenzen bei der Verwendung übereinander? (Angenommen, alles, was ich in den Klammern beider Beispiele mache, ist threadsicher.)

SnickersAreMyFave
quelle

Antworten:

148

Sie machen etwas ganz anderes.

Der erste nimmt den anonymen Delegaten und führt mehrere Threads für diesen Code parallel für alle verschiedenen Elemente aus.

Der zweite ist in diesem Szenario nicht sehr nützlich. Kurz gesagt, es ist beabsichtigt, eine Abfrage für mehrere Threads durchzuführen, das Ergebnis zu kombinieren und es erneut an den aufrufenden Thread weiterzugeben. Der Code in der foreach-Anweisung bleibt also immer im UI-Thread.

Es ist nur sinnvoll, wenn Sie in der Linq-Abfrage rechts neben dem AsParallel()Aufruf etwas Teueres tun , wie:

 var fibonacciNumbers = numbers.AsParallel().Select(n => ComputeFibonacci(n));
svick
quelle
Was ist der Vorteil, wenn Sie einfach eine parallele foreach für die computefibonacci durchführen?
l - '' '' '
51

Der Unterschied ist, dass B nicht parallel ist. Das einzige, was AsParallel()Sie tun müssen, ist, dass es um a gewickelt wird IEnumerable, sodass bei Verwendung von LINQ-Methoden deren parallele Varianten verwendet werden. Der Wrapper GetEnumerator()(der hinter den Kulissen in verwendet wird foreach) gibt sogar das Ergebnis der ursprünglichen Sammlung zurück GetEnumerator().

Übrigens, wenn Sie sich die Methoden in Reflector ansehen möchten, AsParallel()befindet sich in der System.Linq.ParallelEnumerableKlasse in der System.CoreAssembly. Parallel.ForEach()befindet sich in der mscorlibAssembly (Namespace System.Threading.Tasks).

svick
quelle
Was meinst du mit ... Ihre parallelen Varianten werden verwendet ...?
l - '' '' '
2
@punctuation Das heißt zum Beispiel, wenn Sie schreiben .Select(), es ruft ParallelEnumerable.Select()und nicht das normale Enumerable.Select().
Svick
50

Die zweite Methode ist nicht parallel. Die korrekte Verwendung von AsParallel () in Ihrem Beispiel wäre

IEnumerable<string> items = ...

items.AsParallel().ForAll(item =>
{
    //Do parallel stuff here
});
Scott Chamberlain
quelle
3
Warum sollte man die Kombination von asparallel zusammen mit forall verwenden, anstatt einfach foreach?
l - '' '' '