2

144 個のアイテムを含むキューがあります。各キュー要素はリクエストです。コードを並行して実行することで、処理のパフォーマンスを向上させようとしています。performaction(request) メソッドを呼び出します。オブジェクトをインスタンス化し、リクエストを渡してアクションを実行します。これらのリクエストは独立しており、リクエストのアクション結果も互いに独立しているため、このアクションを並行して実行できます。最初に私が試した

foreach(var request in queue.Values)
    Parallel.Invoke(() =>PerformAction(request);

次に、同じforeachを試しました。

var task = new Task(() => PerformAction(request));
task.Start();

そして私が持っているforeachの外

Task.WaitAll();

プログラムを実行すると、parallel.invoke の完了に約 3 秒かかりましたが、Task の完了には約 0.005 秒かかりました。

次の質問があります。

  1. 並列呼び出しがタスクよりも時間がかかったのはなぜですか? 私が望んでいたように、並列呼び出しが並列モードで実行されなかったようです。
  2. Task を使用している場合、リクエストごとに新しい Task を作成しています。リクエストが 1000 リクエストの場合、最終的に 1000 スレッドを作成することになりますか、それとも CPU が必要に応じてスレッドの作成を処理しますか?
  3. Task.WaitAll() は、プログラムが終了する前にすべてのタスクが完了するのを待ちますか?
4

1 に答える 1

9

コードの問題は、Task.WaitAll()意図したとおりに機能しないことです。タスクを保存して開始しました:

var task = new Task(() => PerformAction(request));
task.Start();

しかし、各タスクへの参照を保持していませんWaitAll。すべてのタスクを配列に保存してから、その配列を に渡すことを意図していますWaitAll。したがって、プログラムは終了を待っていないため、タスクで「高速」に実行されます。

あなたの質問:

  1. なぜもっと時間がかかったのかについては、上記を参照してくださいParallel.Invoke-実際に実行されるためです。ただし、正しく使用していません。Parallel.Invoke は一連のアクション ( Actions[]) を受け取り、それらすべてを並行して実行しようとします。毎回単一のアクションで複数回呼び出しています。あなたのコードがどのようにコンパイルされるかさえわかりません。あなたが望むものは次のとおりだと思います:

    Parallel.ForEach(queue.Values, request => PerformAction(request))
    
  2. リクエストごとに新しいタスクを作成していますが、それはスレッドと 1 対 1 でマップされません。デフォルトでは、タスクはスレッド プールを使用します

  3. Task.WaitAll(tasks)tasksすべてが完了するのを待ちます。しかし、何も渡さなければそうではありません。繰り返しますが、これはあなたが持っているようにコンパイルされるべきではありません。

于 2012-04-16T04:15:35.287 に答える