Maison >développement back-end >Tutoriel C#.Net >Introduction détaillée du multithreading C# au pool de threads

Introduction détaillée du multithreading C# au pool de threads

零下一度
零下一度original
2017-06-24 09:38:152739parcourir

Ligne System.Threading.ThreadPool, qui peut être utilisée pour envoyer des éléments de travail, gérer les E/S asynchrones, attendre au nom d'autres threads et gérer les minuteries. Utilisation de base :

        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);
            }
        }

Après avoir exécuté la méthode ThreadPool.QueueUserWorkItem(), le processeur automatiquement sélectionnera un thread dans le pool pour traiter le « contenu du travail " ".

1. Si le pool de threads n'est pas encore en cours d'exécution, un pool de threads sera créé et le premier thread sera démarré.

2. Si le pool de threads est déjà en cours d'exécution et qu'il y a au moins un thread inactif, le pool de threads transmettra le « contenu de travail » au thread inactif pour traitement.

3. S'il n'y a pas de threads inactifs dans le pool de threads à ce moment-là, le travail sera en attente jusqu'à ce qu'il y ait un thread inactif pour le traiter.

Récupérez le nombre de requêtes de pool de threads pouvant être actives en même temps via la méthode ThreadPool.GetMaxThreads().

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

Vous pouvez définir le nombre de requêtes de pool de threads qui peuvent être actives en même temps via la méthode ThreadPool.SetMaxThreads().

      ThreadPool.SetMaxThreads(5, 4);

Cependant, vous ne pouvez pas définir le nombre de threads secondaires ou le nombre de threads d'achèvement d'E/S asynchrones pour qu'il soit inférieur au nombre de processeurs de l'ordinateur. . Le pool de threads est très simple à utiliser, mais il existe certaines restrictions :

1. Tous les threads du pool de threads sont des threads d'arrière-plan. Si tous les threads de premier plan d’un processus se terminent, tous les threads d’arrière-plan s’arrêteront. Le thread entrant dans le pool ne peut pas être remplacé par le thread de premier plan.

2. Vous ne pouvez pas définir la priorité ou le nom du fil entrant dans le pool.

3. Les threads du pool ne peuvent être utilisés que pour des tâches à court terme. Si le thread souhaite s'exécuter tout le temps, vous devez utiliser la classe Thread pour créer un thread.

Passez le paramètre état de l'objet à la tâche JobForAThread() et appelez :

        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);
            }
        }

Opération de contrôle simple

Dans des circonstances normales, une fois le « travail » transféré au pool de threads, il est hors de contrôle. Le processeur décidera automatiquement quand commencer l'exécution (bien sûr, uniquement s'il y a des threads inactifs). Vous pouvez utiliser le code suivant pour que le travail commence à s'exécuter après l'heure spécifiée.

        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);
            }
        }
Résultats d'exécution :

Ici, une fois le travail transmis au pool de threads, le thread est bloqué lors de l'exécution du travail. Dans la phrase mManualEvent.WaitOne();, le travail ne continuera pas à exécuter le code suivant jusqu'à ce que le thread principal envoie un signal 10 secondes plus tard. Il s'agit d'une opération de contrôle de

"faux départ"

qui ne permet essentiellement pas au travail spécifié de commencer à fonctionner au moment prévu. Ici, lors de l'initialisation de l'objet ManualResetEvent, le paramètre false signifie que le signal est défini sur "l'état de blocage" par défaut et que le signal est défini sur "l'état continu" via le code mManualEvent.Set();. Au contraire, vous pouvez mettre le fil en "état bloqué" via le code mManualEvent.Reset();.

Lorsqu'il y a , vous devez attendre que tous les threads du pool de threads terminent leur exécution avant de continuer à exécuter un autre code.

        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();
        }
Résultat de l'exécution :

[]

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Déclaration:
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn