4

バックグラウンドでジョブを順番に実行することを目的とする Backgroundworker があります。現在、1 つのジョブがマルチスレッド方式で実装されています。つまり、Backgroundworker は複数のスレッドを作成します。私は Task Parallel Library を使用しているので、Task.Factory.StartNew を使用して複数のタスクを作成します。

タスクが実行された後、Backgroundworker はすべてのタスクが完了するまで待機します。

次に、Backgroundworker の ManagedThreadID とすべてのタスクの ManagedThreadID を出力します。BackgroundWorker の ManagedThreadID は常に最初のタスクの ManagedThreadID と同じであることがわかりました。これはあってはならないことだと思うので、説明できません。Backgroundworker のスレッドは、それが作成するすべてのタスクとは異なる必要があるため、ManagedThreadID はすべて互いに異なる必要があると思います。

このシナリオが発生する理由を説明できる人はいますか? どうもありがとうございました。

編集:

コードは次のようになります。

Backgroundworker.Run(){
    // Print Thread.CurrentThread.ManagedThreadID.
    var task = Task.Factory.StartNew(action1); // action1, action2 also print ManagedThredID.
    taskList.Add(task);
    task = Task.Factory.StartNew(action2);
    taskList.Add(task);
    ... // Several other tasks.

    foreach(var task in taskList) task.Wait();
}

1 つのタスクが Backgroundworker と同じ ManagedThreadID を持っていることがわかります。

4

4 に答える 4

5

ここでは、TPL がBackgroundWorkerスレッドを再利用するのに十分なほどスマートであると推測します。ワーカーはすべてのタスクが完了するのを待つため、同じスレッドで 1 つのタスクを実行することはおそらく最適化です。

Task.Waitさらに調査した結果、表示されているのはメソッドの予想される動作の結果です。詳細については、Task.Wait およびParallel Programming Team ブログの「インライン化」を参照してください。

待機中のタスクが既に実行を開始している場合、待機はブロックする必要があります。ただし、実行が開始されていない場合、Wait は、キューに入れられていたスケジューラーからターゲット タスクを引き出し、現在のスレッドでインラインで実行できる場合があります。

于 2010-09-17T12:08:13.267 に答える
2

あなたがつまずいたのは、もちろん問題ではなく機能 (最適化) です。TPL は可能な限りスレッドを再利用しています。

タスクを作成しても、すぐにまたは永続的にスレッドに関連付けられるわけではありません。タスクはキューに入れられるジョブであり、キューはワーカー スレッドによって処理されます。そのため、Bgw タスクが中断され、そのスレッドがプールに戻された可能性があります。または、より直接的に Wait() によって実行された可能性があります。

// thread A
var t1 = Task.Startnew(...);
var t2 = Task.Startnew(...);
t1.Wait();  // Thread A is idle/available so Wait can execute t1
t2.Wait();  
于 2010-09-17T12:27:00.507 に答える
2

バックグラウンド ワーカーは、スレッド プールと TPL からスレッドを引き出します。バックグラウンド ワーカーが開始されると、プールからスレッドが引き出され、TPL スレッドが開始され、すぐにスレッドがプールに返されます。TPL の最初のタスクが実行されるまでに、TPL はプールからスレッドを取得し、バックグラウンド ワーカーによって使用されたスレッドと同じスレッドを選択することがあります。

もちろん、それはコードを示していないため検証できない単なる仮定です。

于 2010-09-17T12:06:26.360 に答える
1

バックグラウンド ワーカーの再利用を避けるには、TaskCreationOptions.LongRunning を使用します。

于 2011-02-12T20:31:09.127 に答える