ホームページ >バックエンド開発 >C#.Net チュートリアル >C# マルチスレッド - スレッド プールの詳細な概要

C# マルチスレッド - スレッド プールの詳細な概要

零下一度
零下一度オリジナル
2017-06-24 09:38:152738ブラウズ

System.Threading.ThreadPool。作業項目の送信、非同期 I/O の処理、他のスレッドに代わって待機、タイマーの処理に使用できます。基本的な使用法:

        public void Main()
        {
            ThreadPool.QueueUserWorkItem(JobForAThread); // 将某工作交给线程池}void JobForAThread(object state) // 线程要执行的工作:满足 委托WaitCallback        {for (int i = 1; i <= 5; i++)
            {
                Console.WriteLine("Running Thread {0},Step {1}", Thread.CurrentThread.ManagedThreadId, i);
                Thread.Sleep(500);
            }
        }

ThreadPool.QueueUserWorkItem() メソッドを実行した後、プロセッサは、「作業コンテンツ」を処理するためにプール内のスレッドを 自動的に 選択します。

1. スレッド プールがまだ実行されていない場合は、スレッド プールが作成され、最初のスレッドが開始されます。

2. スレッド プールがすでに実行中で、アイドル状態のスレッドが少なくとも 1 つある場合、スレッド プールは処理のために「作業コンテンツ」をこのアイドル状態のスレッドに渡します。

3. その時点でスレッド プールにアイドル状態のスレッドがない場合、ジョブは処理するアイドル状態のスレッドができるまで待機状態になります。

ThreadPool.GetMaxThreads() メソッドを通じて、同時にアクティブにできるスレッド プール リクエストの数を取得します。

            int vWorkerThreads; int vCompletionPortThreads;
            ThreadPool.GetMaxThreads(out vWorkerThreads, out vCompletionPortThreads);
            Console.WriteLine("池中辅助线程的最大数{0},池中异步 I/O 线程的最大数{1}", vWorkerThreads, vCompletionPortThreads);

ThreadPool.SetMaxThreads() メソッドを通じて、同時にアクティブにできるスレッド プール リクエストの数を設定できます。

ThreadPool.SetMaxThreads(5, 4);

ただし、補助スレッドの数や非同期 I/O 完了スレッドの数をコンピューターのプロセッサーの数よりも小さく設定することはできません。スレッド プールの使用は非常に簡単ですが、いくつかの制限があります:

1. スレッド プール内のすべてのスレッドはバックグラウンド スレッドです。プロセスのすべてのフォアグラウンド スレッドが終了すると、すべてのバックグラウンド スレッドが停止します。プールに入ったスレッドをフォアグラウンド スレッドに変更することはできません。

2. プールに入るスレッドの優先順位や名前を設定することはできません。

3. プール内のスレッドは、短期間のタスクにのみ使用できます。スレッドを常に実行したい場合は、Thread クラスを使用してスレッドを作成する必要があります。

パラメーター オブジェクトの状態を JobForAThread() ジョブ タスク に渡し、呼び出し:

        public void Main()
        {
            ThreadPool.QueueUserWorkItem(JobForAThread,"这是传递给工作内容的参数"); // 添加工作的同时,传递参数Console.ReadKey(); // 让主线程等待,否则“一闪而过”        }void JobForAThread(object state) 
        {
            Console.WriteLine("收到信息:{0}", (string)state); // 处理传进来的数据for (int i = 1; i <= 5; i++)
            {               
                Console.WriteLine("Running Thread {0},Step {1}", Thread.CurrentThread.ManagedThreadId, i);
                Thread.Sleep(500);
            }
        }

単純な制御操作

通常の状況では、 「作業」はスレッド プールに渡され、制御不能になります。いつ実行を開始するかはプロセッサによって自動的に決定されます (もちろん、アイドル状態のスレッドがある場合に限ります)。次のコードを使用すると、指定した時間後にジョブの実行を開始できます。

        ManualResetEvent mManualEvent;public void Main()
        {
            mManualEvent = new ManualResetEvent(false); // 实例ThreadPool.QueueUserWorkItem(JobForAThread);

            Console.WriteLine("{0} 任务已经交给线程池了,但是它没有执行.", DateTime.Now.ToString("HH:mm:ss"));
            Thread.Sleep(10000); // 等待 10smManualEvent.Set();  // 发出信号,让线程继续执行           
            Console.ReadKey(); // 让主线程等待,否则“一闪而过”        }void JobForAThread(object state) 
        {
            mManualEvent.WaitOne(); // 等待 “ mManualEvent.Set();” 这一句执行(发送信号)Console.WriteLine("{0} 现在开始执行任务啦.", DateTime.Now.ToString("HH:mm:ss"));for (int i = 1; i <= 5; i++)
            {               
                Console.WriteLine("Running Thread {0},Step {1}", Thread.CurrentThread.ManagedThreadId, i);
                Thread.Sleep(500);
            }
        }
実行結果:

ここで、作業がスレッド プールに渡された後、スレッドが作業を実行すると、メイン スレッドが10 秒後に信号が送信され、後続のコードの実行が続行されます。これは

「誤った開始」

制御操作であり、基本的に、指定された作業が予期されたときに動作を開始することを許可しません。ここで、ManualResetEvent オブジェクトを初期化するとき、パラメーター false は、信号がデフォルトで「ブロック状態」に設定され、コード mManualEvent.Set(); によって信号が「継続可能状態」に設定されることを意味します。逆に、コード mManualEvent.Reset(); を使用して、スレッドを「ブロック状態」にすることができます。

がある場合、他のコードの実行を続ける前に、スレッド プール内のすべてのスレッドが実行を完了するまで待つ必要があります。

        AutoResetEvent[] mAutoResetEvent;public void Main()
        {
            mAutoResetEvent = new AutoResetEvent[]{new AutoResetEvent(false), // 默认信号为 阻塞new AutoResetEvent(false),new AutoResetEvent(false)
            };for (int i = 0; i < 3; i++) // 创建3个工作            {
                Thread.Sleep(1000);
                ThreadPool.QueueUserWorkItem(JobForAThread, i); 
            }
            Console.WriteLine("所有工作已经添加到池中...");
            WaitHandle.WaitAll(mAutoResetEvent); // 等待 mAutoResetEvent 中所有信号变为 继续 后,继续后面代码Console.WriteLine("所有工作已经完成了");

            Console.ReadKey(); // 让主线程等待,否则“一闪而过”        }void JobForAThread(object state) 
        {int vJobIndex = (int)state;
            Console.WriteLine("Job {0} Started.", vJobIndex);for (int i = 1; i <= 5; i++)
            {
                Console.WriteLine("Running Thread {0},Step {1},Job {2} ", Thread.CurrentThread.ManagedThreadId, i, vJobIndex);
                Thread.Sleep(500);
            }

            mAutoResetEvent[vJobIndex].Set();
        }
実行結果:

[]

以上がC# マルチスレッド - スレッド プールの詳細な概要の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。