web-dev-qa-db-ja.com

AsParallel.ForAllとParallel.ForEach

以下のコードスニペットに違いはありますか。もしそうなら、何?

myList.AsParallel().ForAll(i => { /*DO SOMETHING*/ });

そして

Parallel.ForEach(mylist, i => { /*DO SOMETHING*/ });

メインスレッドは、すべての子スレッドが完了するまで待機しますか? MVCアプリケーションでは、コントローラーアクションで並列処理を実行している場合、メインスレッドの完了後に子スレッドに何が起こります。メインスレッドが完了した後でも、それらは中止されますか?

33
Dhawal

Parallel.ForEach()は、まさにこの種のコードを対象としています。

一方、ForAll()は、(おそらく複雑な)PLINQクエリの終わりに使用することを目的としています。

そのため、ここではParallel.ForEach()がより良い選択だと思います。

どちらの場合も、現在のスレッドは(スレッドプールの一部のスレッドとともに)計算を実行するために使用され、メソッドはすべての処理が完了した後にのみ戻ります。

22
svick

MSDNの説明は次のとおりです。

https://docs.Microsoft.com/en-us/dotnet/standard/parallel-programming/potential-pitfalls-with-plinq#prefer-forall-to-foreach-when-it-is-possible

私が読んだことに基づいて、リストにアクセスできることを確認したい場合はParallel.ForEach()を使用しますsequentiallyで、AsParallel.ForAll()を使用してもリスト内のアイテムが順番にアクセスされることを保証しません。

MVCの場合、すべてのスレッドは要求ベースです。呼び出し元スレッド(メイン)は、Parallel()呼び出しが完了するまでブロックされます。つまり、すべての子スレッドも同様に完了する必要があります。

呼び出し元のスレッドが異常終了している場合、説明を次に示します。

http://www.albahari.com/threading/part5.aspx

PLINQはスレッドをプリエンプティブに中止しません。スレッドを中止する危険性があるためです。代わりに、キャンセルすると、各ワーカースレッドが現在の要素で終了するのを待ってからクエリを終了します。これは、クエリが呼び出す外部メソッドが完了するまで実行されることを意味します。

1
dsum