web-dev-qa-db-ja.com

ThreadPoolを使用する適切な方法は何ですか?

ThreadPoolの動作方法に関する私の理解が正しい場合、その目的の1つは、特定の時間に作成できるプロセス内のワーカースレッドの数を制限することです。たとえば、MaxThreadsを5に設定してからQueueUserWorkItemを30回呼び出すと、30のリクエストがThreadPoolに対して行われますが、それらのリクエストのうち5つだけが新しいスレッドによって処理され、他の25のリクエストはキューに追加されます以前のリクエストが完了し、既存のスレッドが利用可能になったときに一度に1つずつサービスを提供しました。

ただし、以下のコードでは、Thread.Sleep(-1)の呼び出しにより、DoSomething()メソッドが返されないことが保証されます。つまり、現在のスレッドは後続の要求で使用できなくなります。

ただし、ThreadPoolの動作方法についての私の理解は正しくありません。正しい場合、以下のコードは0〜29ではなく0〜4の数字のみを出力するからです。

誰かがThreadPoolがどのように機能するのか、そして以下のコードが私が思っていることをしていないのはなぜですか?

    static void DoSomething(object n)
    {
        Console.WriteLine(n);
        Thread.Sleep(-1);
    }

    static void Main(string[] args)
    {
        ThreadPool.SetMaxThreads(5, 5);
        for (int x = 0; x < 30; x++)
        {
            ThreadPool.QueueUserWorkItem(new WaitCallback(DoSomething), x);
        }
        Console.Read();
    }
23
John Smith

ThreadPool.SetMaxThreads(5, 5)

アクティブなスレッドの数が5(CPUコアが5つを超える場合)であることを意味しますが、ThreadPoolが作成できるスレッドは5つだけであることを意味しません。 ThreadPoolの最大スレッド数= CPUコア* 250。

Thread.Sleepの後、スレッドは非アクティブであるため、他のスレッドの実行には影響しません。

18
shalongbus

ただし、ThreadPoolの動作方法についての私の理解は正しくありません。正しい場合、以下のコードは0〜29ではなく0〜4の数字のみを出力するからです。

はい、あなたの仮定は非常に正しいです。

UはThreadPoolで30個のジョブをキューに入れており、ジョブはInfiniteTimeの間スリープ状態になるため、ジョブは終了せず、ThreadPoolクラスは新しいスレッドを作成するために一定の間隔を待機しますが、スレッドの最大数を超えません。

注意

Console.Read()は、バックグラウンドスレッドを存続させます。

記事

MSDNから

多くのアプリケーションは、スリープ状態で長時間を費やし、イベントの発生を待機するスレッドを作成します。他のスレッドはスリープ状態に入り、定期的に起動されてステータス情報の変更または更新をポーリングする場合があります。スレッドプーリングを使用すると、システムが管理するワーカースレッドのプールをアプリケーションに提供することで、スレッドをより効率的に使用できます。 1つのスレッドは、スレッドプールにキューイングされているいくつかの待機操作のステータスを監視します。待機操作が完了すると、スレッドプールのワーカースレッドが対応するコールバック関数を実行します。


すべてのスレッドプールスレッドがタスクに割り当てられると、スレッドプールはすぐに新しいアイドルスレッドの作成を開始しません。スレッドに不必要にスタックスペースを割り当てることを避けるために、間隔で新しいアイドルスレッドを作成します。間隔は現在0.5秒ですが、.NET Frameworkの将来のバージョンでは変更される可能性があります。


マネージスレッドプール内のスレッドはバックグラウンドスレッドです。つまり、IsBackgroundプロパティはtrueです。これは、すべてのフォアグラウンドスレッドが終了した後、ThreadPoolスレッドがアプリケーションの実行を維持しないことを意味します。

4
PaRiMaL RaJ

Thread.Sleep(-1)が期待どおりに動作していない可能性があります。

パラメーターInt32:スレッドがブロックされるミリ秒数。ゼロ(0)を指定して、他の待機スレッドの実行を許可するためにこのスレッドを中断する必要があることを示します。スレッドを無期限にブロックするには、Infiniteを指定します。

http://msdn.Microsoft.com/en-us/library/d00bd51t.aspx

タスクを調べる必要があります http://msdn.Microsoft.com/en-us/library/dd235608.aspx Threadpool 2.0と考えてください

2
Austin Harris

通常、ThreadPoolはCPUコアの数に等しい数のスレッドを作成します。一度に1つのスレッドしかコアで処理できないため、追加のスレッドを作成する必要はありません。ただし、ThreadPoolのキューに入れられたタスクの実行に0.5秒以上かかると、ThreadPoolは追加のスレッドを作成して、キュー内の残りのタスクを処理します。したがって、多数の重いタスクをThreadPoolのキューに入れると、マルチタスクをエミュレートし、すべてのタスクを「並列」で実行するための追加のスレッドが多数作成されます。ただし、合計実行時間は、スレッドを追加しない場合と同じになります。さらに、スレッドの作成は非常に重い操作であるため、さらに短くなります。そのため、実際には利点をもたらさない追加のスレッドの作成を避けるため、小さなタスクにはThreadPoolが推奨されます。

ThreadPoolの詳細については、 Albahari's の記事をご覧ください。実際、彼にはスレッド化に関する良い記事があります。