1. ホーム
  2. c#

[解決済み】Parallel.ForEachとTask.Factory.StartNewの比較

2022-04-02 20:03:57

質問

以下のコードスニペットの違いは何ですか?どちらもスレッドプールスレッドを使用するのではありませんか?

例えば、コレクション内の各項目に対して関数を呼び出したい場合。

Parallel.ForEach<Item>(items, item => DoSomething(item));

vs

foreach(var item in items)
{
  Task.Factory.StartNew(() => DoSomething(item));
}

解決方法は?

1つ目は、より良い選択肢です。

Parallel.ForEachは、内部的には Partitioner<T> を使用して、コレクションをワークアイテムに分散させます。 1つのアイテムに1つのタスクを実行するのではなく、バッチ処理でオーバーヘッドを低減します。

2番目のオプションは、1つの Task コレクション内のアイテムごとに 結果はほぼ同じですが、特に大きなコレクションの場合、必要以上のオーバーヘッドが発生し、全体の実行時間が遅くなります。

参考までに - 使用されるパーティショナーは、適切な をオーバーロードしたものです。 を使用します。 詳しくは カスタムパーティショナー をMSDNでご覧ください。

実行時の主な違いは、2番目の動作が非同期であることです。 これは、Parallel.ForEachを使うことで、複製することができます。

Task.Factory.StartNew( () => Parallel.ForEach<Item>(items, item => DoSomething(item)));

こうすることで、パーティショナーの利点を生かしつつ、操作が完了するまでブロックしないようにします。