.Net で ThreadPool を使用すべきでないのはどのような場合ですか?[閉まっている]

StackOverflow https://stackoverflow.com/questions/10274

質問

いつ行えばよいですか ない .Net で ThreadPool を使用しますか?

ThreadPool を使用するのが最善の選択肢のように見えますが、その場合、なぜそれが唯一の選択肢ではないのでしょうか?

この点についてはどのような経験がありますか?

役に立ちましたか?

解決

私が使わない唯一の理由は、 ThreadPool 安価なマルチスレッドが必要な場合は…

  1. 実行中のメソッドと対話します (メソッドを強制終了するなど)
  2. コードを実行する STAスレッド (これは私に起こりました)
  3. アプリケーションが終了した後もスレッドを存続させてください(ThreadPool スレッドはバックグラウンド スレッドです)
  4. スレッドの優先順位を変更する必要がある場合に備えて。ThreadPool 内のスレッドの優先順位は変更できません。デフォルトでは [Normal] になっています。

追記: MSDN の記事 「マネージド スレッド プール」 というタイトルのセクションが含まれています。 「スレッドプールスレッドを使用しない場合」, 、非常に似ていますが、スレッド プールを使用しない考えられる理由のもう少し完全なリストが含まれています。

スキップする必要がある理由はたくさんあります。 ThreadPool, 、しかし、それらを知らない場合は、 ThreadPool あなたにとっては十分なはずです。

あるいは、新しいものを見てください。 並列拡張フレームワーク, 、そこには、 ThreadPool.

他のヒント

@エリック、私はディーンに同意する必要があります。糸は高価です。自分のプログラムだけが実行されていると想定することはできません。誰もがリソースに貪欲になると、問題はさらに増大します。

私はスレッドを手動で作成し、自分で制御することを好みます。コードが非常に理解しやすくなります。

適当なときはそれでいいです。ただし、多数のワーカー スレッドが必要な場合は、コードをより複雑にするだけです。次に、それらを管理するコードを記述する必要があります。スレッド プールを使用しただけであれば、すべてのスレッド管理を無料で利用できます。また、言語によって提供されるスレッド プールは、自分で作成したスレッド プールよりも堅牢で効率的で、バグが少ない可能性が非常に高くなります。

Thread t = new Thread(new ThreadStart(DoSomething));  
t.Start();  
t.Join();  

通常は間に追加のコードを入れていただければ幸いです Start() そして Join(). 。そうしないと、余分なスレッドは役に立たず、理由もなくリソースを浪費することになります。

人々はスレッドによって使用されるリソースをあまりにも恐れています。スレッドの作成と開始に 1 ミリ秒以上かかるのを見たことがありません。作成できるスレッドの数に厳密な制限はありません。RAM の使用量は最小限です。スレッドが数百になると、コンテキストの切り替えにより CPU が問題になるため、その時点でデザインを工夫したくなるかもしれません。

ミリ秒とは、 長さ 最新のハードウェアでの時間。これは、3GHz マシンでは 300 万サイクルに相当します。繰り返しますが、スレッドを作成しているのはあなただけではありません。スレッドは、他のすべてのプログラムのスレッドと同様に CPU をめぐって競合します。それほど多くないスレッドを使用し、別のプログラムも使用する場合は、両方とも使用したスレッドが多すぎることになります。

真剣に、人生を必要以上に複雑にしないでください。スレッド プールが提供する非常に特殊な機能が必要な場合を除き、スレッド プールを使用しないでください。

確かに。人生をこれ以上複雑にしないでください。プログラムに複数のワーカー スレッドが必要な場合は、車輪の再発明は必要ありません。スレッドプールを使用します。だからこそそこにあるのです。独自の文字列クラスを開発してみませんか?

ワーカー スレッドの概念がある場合、スレッド プールは意味を持ちます。処理をより小さなジョブに簡単に分割でき、各ジョブを独立して処理できる場合には、ワーカー スレッド (したがってスレッド プール) が意味を持ちます。

スレッド プールは、「ジョブ」とはみなされない、まったく異なる無関係なアクションを実行するスレッドが必要な場合には意味がありません。たとえば、1 つのスレッドは GUI イベント処理用で、もう 1 つのスレッドはバックエンド処理用です。スレッド プールは、パイプラインを処理する場合にも意味がありません。

基本的に、開始、ジョブの処理、および終了を行うスレッドがある場合は、おそらくスレッド プールが最適です。それ以外の場合、スレッド プールは実際には役に立ちません。

喧嘩好きの答えとしては、スレッドがすぐに動作を開始することを保証する必要がある場合は、ThreadPool スレッドを使用しないのが最善であると付け加えます。実行中のスレッド プールされたスレッドの最大数はアプリドメインごとに制限されているため、すべてのスレッドがビジー状態の場合、作業は待機する必要がある場合があります。結局のところ、それは「キューユーザーワークアイテム」と呼ばれます。

もちろん、次の 2 つの注意点があります。

  1. スレッド プールされたスレッドの最大数は実行時にコード内で変更できるため、現在の数と最大数を確認し、必要に応じて最大数を増やすことを妨げるものはありません。
  2. 新しいスレッドをスピンアップするには、それ自身の時間ペナルティが伴います。ヒットを受ける価値があるかどうかは、状況によって異なります。

私はここで理論的な知識だけを持っている人として話しているわけではありません。私は、マルチスレッドを豊富に使用する大量のアプリケーションを書き、維持していますが、一般的にスレッドプールが正しい答えであるとは思いません。

ああ、権威者からの議論ですが、Windows カーネル チームに所属している可能性のある人には常に注意してください。

私たち二人とも、特定の要件がある場合には .NET ThreadPool が適切ではない可能性があるという事実に異論はありませんでした。私たちが反対しているのは、スレッドを作成するマシンのコストを単純化することです。

そもそも ThreadPool の存在意義は、スレッドの作成に多大な費用がかかることです。私は、スレッドの作成に費用がかかるという誤解をした人々が書いたコードで私のマシンがいっぱいになることを望んでいません。たとえば、スレッドの作成により、すべての DLL でメソッドが呼び出されるということを知りません。プロセスに接続されており (一部はサードパーティによって作成されます)、RAM にまったく存在する必要がなく、ほぼ確実に L1 に存在する必要のないコードの負荷がホットアップされる可能性があります。

最新のマシンのメモリ階層の形状を考えると、CPU の「注意をそらす」ことは考えられる最悪の行為であり、自分の技術に関心を持つ人は皆、それを避けるために懸命に努力する必要があります。

長時間かかる操作、または継続的なバックグラウンド スレッドを実行する場合。プール内で使用可能なスレッドの量をいつでも増やすことはできると思いますが、プールに返されることのないスレッドの管理コストが発生するのはほとんど意味がありません。

MSDN には、いくつかの理由がリストされています。

http://msdn.microsoft.com/en-us/library/0ka9477y.aspx

スレッドプールスレッドを使用する代わりに、独自のスレッドを作成および管理することが適切なシナリオがいくつかあります。

  • フォアグラウンド スレッドが必要です。
  • スレッドに特定の優先順位を持たせる必要があります。
  • スレッドが長時間ブロックされる原因となるタスクがあります。スレッドプールには最大数のスレッドがあるため、多数のブロックされたスレッドプールスレッドがタスクの開始を防ぐ可能性があります。
  • スレッドをシングルスレッド アパートメントに配置する必要があります。すべての ThreadPool スレッドはマルチスレッド アパートメント内にあります。
  • スレッドに安定した ID を関連付けるか、スレッドをタスク専用にする必要があります。

スレッドプール スレッドは、次の両方の基準を満たすタスクに適しています。

  1. タスクは何かが起こるのを待つためにかなりの時間を費やす必要がありません
  2. タスクが完了するのを待っているものは、多くのタスクが完了するのを待っている可能性が高いため、そのスケジュールの優先順位は物事にあまり影響を与えません。

新しいスレッドを作成する代わりにスレッドプール スレッドを使用すると、大幅ではありますが時間を節約できます。その時間がタスクの実行にかかる時間と比較して重要な場合は、スレッドプール タスクが適切である可能性があります。ただし、タスクの実行に必要な時間が長くなるほど、スレッドプールを使用するメリットは小さくなり、タスクがスレッドプールの効率を妨げる可能性が高くなります。

@エリック

@デレク、私はあなたが例として使用したシナリオにはまったく同意しません。マシン上で何が実行されているか、またアプリが一定の負荷の下で使用するスレッド、ハンドル、CPU 時間、RAM などの合計数が正確にわからない場合は、問題が発生します。

あなたが作成したプログラムの対象顧客はあなただけですか?そうでなければ、そのほとんどについて確信を持てません。通常、プログラムを作成するときには、そのプログラムが単独で効果的に実行されるかどうか、それとも DDOS 攻撃にさらされている Web サーバー上で実行されるかどうかはわかりません。CPU 時間がどのくらいになるかはわかりません。

プログラムの動作が入力に基づいて変化すると仮定すると、プログラムが消費するメモリや CPU 時間の量を正確に知ることさえほとんどありません。確かに、プログラムがどのように動作するかについてはかなりよく理解しているはずですが、ほとんどのプログラムは、メモリの量やハンドルの数などを正確に決定するために分析されることはありません。完全な分析はコストがかかるため、使用されます。リアルタイム ソフトウェアを作成していない場合、労力を費やす価値はありません。

一般に、プログラムがどのように動作するかを正確に知っていると主張するのは突飛であり、マシンについてすべてを知っていると主張するのはばかげています。

正直に言うと、どの方法を使用すればよいか正確にわからない場合は、次のようにします。手動スレッド、スレッドプール、デリゲート、そしてアプリケーションが必要なことを実行するためにそれを実装する方法について考えていたら、あなたは困っています。

完全に同意するわけではありませんが、それがどのように関連しているのかはわかりません。このサイトがここにあるのは、プログラマーが常にすべての答えを持っているわけではないためです。

使用するスレッドの数を調整する必要があるほどアプリケーションが複雑な場合、ほとんどの場合、フレームワークが提供する以上の制御が必要になるのではないでしょうか?

いいえ。スレッド プールが必要な場合は、十分ではない場合を除き、提供されているものを使用します。実際にそうであることを確認せずに、提供されたスレッド プールが私のニーズには不十分であると単純に仮定するつもりはありません。

私はここで理論的な知識しかない人間として話しているのではありません。私はマルチスレッドを多用する大容量アプリケーションを作成および保守していますが、通常、スレッド プールが正しい答えであるとは思いません。

私の専門的な経験のほとんどは、マルチスレッドおよびマルチプロセッシング プログラムに関するものです。私も独自のソリューションを展開する必要があることがよくありました。これは、スレッド プールが役に立たない、または多くの場合に適切ではないという意味ではありません。スレッド プールは、ワーカー スレッドを処理するために構築されます。複数のワーカー スレッドが適切な場合は、通常、提供されたスレッド プールを最初のアプローチにする必要があります。

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top