web-dev-qa-db-ja.com

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

Erg、Reflectorを使用してBCLでこれら2つのメソッドを見つけようとしていますが、見つけることができません。これら2つのスニペットの違いは何ですか?

A:

IEnumerable<string> items = ...

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

B:

IEnumerable<string> items = ...

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

どちらか一方を使用すると異なる結果がありますか? (両方の例の括弧で囲まれた本文で私がしていることはすべてスレッドセーフであると仮定します。)

140

彼らは全く違うことをします。

1つ目は匿名デリゲートを受け取り、このコードで複数のスレッドをすべての異なるアイテムに対して並行して実行します。

2番目は、このシナリオではあまり役に立ちません。簡単に言うと、複数のスレッドでクエリを実行し、結果を結合して、呼び出し元のスレッドに再度渡すことを目的としています。そのため、foreachステートメントのコードは常にUIスレッドに留まります。

次のように、AsParallel()呼び出しの右側にあるlinqクエリで高価な操作を行う場合にのみ意味があります。

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

違いは、Bは平行ではないということです。 AsParallel()が行う唯一のことは、IEnumerableをラップすることです。そのため、LINQメソッドを使用すると、それらの並列バリアントが使用されます。ラッパーのGetEnumerator()foreachの背後で使用されます)は、元のコレクションのGetEnumerator()の結果も返します。

ところで、Reflectorのメソッドを見たい場合、AsParallel()System.Linq.ParallelEnumerableアセンブリのSystem.Coreクラスにあります。 Parallel.ForEach()mscorlibアセンブリ(名前空間System.Threading.Tasks)にあります。

49
svick

2番目の方法は並列ではなく、例でAsParallel()を使用する正しい方法は次のようになります。

IEnumerable<string> items = ...

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