线程池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.如果线程池已经在运行,且至少有一个空闲的线程,线程池就会把改“工作内容”交给这个空闲的线程来处理。

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() 工作任务传递参数 object state,调用:

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

运行结果:

这里在将工作交给线程池后,线程执行工作时,一直阻塞在 mManualEvent.WaitOne(); 这一句,直到10s后主线程发出了信号,该工作才继续执行后续代码。这是一种“假开始”控制操作,本质上并没有实现让指定工作在希望的时候开始工作。这里 在初始化 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中文网其它相关文章!

声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn核实处理。

  • 相关标签:csharp .net 线程
  • 程序员必备接口测试调试工具:点击使用

    Apipost = Postman + Swagger + Mock + Jmeter

    Api设计、调试、文档、自动化测试工具

    网页生成APP,用做网站的技术去做APP:立即创建

    手机网站开发APP、自助封装APP、200+原生模块、2000+映射JS接口按需打包

    • 上一篇:什么是委托?总结.net中重要的特性委托
    • 下一篇:C#中SQL参数传入空值出错误和如何解决办法

    相关文章

    相关视频


    • c语言中goto语句的含义是什么
    • C/C++深度分析
    • C#中GDI+编程10个基本技巧二
    • 应用绝对路径与相对路径
    • C# 多线程--线程池的详细介绍
    • ASP.NET 简介
    • ASP.NET 教程
    • ASP.NET 简介
    • ASP.NET 教程
    • ASP.NET 简介

    视频教程分类

    • php视频教程
    • html视频教程
    • css视频教程
    • JS视频教程
    • jQuery视频教程
    • mysql视频教程
    • Linux视频教程
    • Python视频教程
    • Laravel视频教程
    • Vue视频教程

    专题

    C# 多线程--线程池的详细介绍