web-dev-qa-db-ja.com

Thread.Start()対ThreadPool.QueueUserWorkItem()

Microsoft .NET基本クラスライブラリには、スレッドを作成して開始するいくつかの方法が用意されています。基本的に、呼び出しは同じ種類のサービスを提供する他のすべてのものと非常に似ています:実行フロー(またはそれ以上)を表すオブジェクトを作成し、実行する実行フローを表すデリゲートを割り当て、最終的にはデリゲートシグネチャに応じてオブジェクトパラメータとして。

まあ、2つのアプローチがあります(本質的に):

1)System.Threading.Threadクラスを使用します。

Thread curr = new Thread(myfunction); /* In a class, myfunction is a void taking an object */
curr.Start(new Object()); /* Or something else to be downcast */

2)System.Threading.ThreadPoolクラスを使用します。

ThreadPool.QueueUserWorkItem(myfunction, new Object()); /* Same philosophy here */

1)または2)を使用する特別な理由はありますか?

  • パフォーマンス上の理由?
  • パターン?
  • 最善のアプローチは何ですか?

答えは「状況に依存する」という感じがします。あるアプローチが別のアプローチよりも優れている状況をいくつか挙げてください。

41
Andry

新しいスレッドの開始は、非常に高価な操作になる場合があります。スレッドプールはスレッドを再利用するため、コストを償却します。専用のスレッドが必要でない限り、スレッドプールが推奨されます。専用スレッドを使用することにより、優先度、カルチャなどのスレッド固有の属性をより詳細に制御できます。また、スレッドプールで追加のスレッドを強制的に生成するため、スレッドプールで長時間実行されるタスクを実行しないでください。

あなたが言及したオプションに加えて、.NET 4は並行性のためのいくつかの素晴らしい抽象化を提供します。 TaskクラスとParallelクラス、およびすべての新しいPLINQメソッドを確認してください。

46
Brian Rasmussen

マネージスレッドプール には、スレッドプールを使用しない場合に関する非常に優れたガイドラインがあります。

私の経験では、永続的で専用の長時間実行されるスレッドが必要な場合、独自のスレッドを作成したいと考えています。それ以外の場合は、非同期デリゲートまたはQueueUserWorkItemBackgroundWorker、または.NET 4.0のタスク関連機能などを使用します。

12
Jim Mischel

ThreadPoolのスレッドはバックグラウンドスレッドです。新しいThreadオブジェクトによって作成および開始されるすべてのスレッドは、フォアグラウンドスレッドです。

バックグラウンドスレッドは、マネージ実行環境を実行し続けません。

詳細については http://msdn.Microsoft.com/en-us/library/h339syd0.aspx を参照してください。

7
Steel

.NET 4.5.2では、新しいメソッド HostingEnvironment.QueueBackgroundWorkItem が追加されました。

これは、ThreadPool.QueueUserWorkItemの代替と思われます。どちらも同じように動作しますが、ASP.NETで作業するときに新しいメソッドを使用すると、次のような利点があります。

HostingEnvironment.QueueBackgroundWorkItemメソッドを使用すると、小さなバックグラウンド作業項目をスケジュールできます。 ASP.NETはこれらの項目を追跡し、すべてのバックグラウンド作業項目が完了するまでIISがワーカープロセスを突然終了するのを防ぎます。このメソッドは、ASP.NET管理アプリドメインの外部で呼び出すことはできません。

6
dana

ThreadPoolを使用すると、スレッドシステムの制御が少なくなります。これは、プロセスを簡素化するためのトレードオフです。 ThreadPoolから必要なものがすべて揃っている場合は、気軽に利用してください。スレッドをさらに制御する必要がある場合は、もちろんThreadクラスを使用する必要があります。

2
Bueller

ThreadPool.QueueUserWorkItem()は、アプリケーションが操作が終了するかどうかに依存しない場合、基本的には火災と忘却のシナリオ用です。

細かく制御するには、クラシックスレッドを使用します。

1
Tomas Voracek

次の場合を除き、ThreadPool.QueueUserWorkItemを使用する必要があります。

  • フォアグラウンドスレッドが必要です。

  • スレッドには特定の優先順位が必要です。

  • スレッドを長時間ブロックするタスクがあります。スレッドプールには最大数のスレッドがあるため、ブロックされたスレッドプールスレッドが多数あると、タスクの開始が妨げられる可能性があります。

  • スレッドをシングルスレッドアパートメントに配置する必要があります。すべてのThreadPoolスレッドはマルチスレッドアパートメントにあります。

  • スレッドに関連付けられた安定したIDを持つか、スレッドをタスク専用にする必要があります。

参照 リンク

0
sotn