异步多线程(三)ThreadPool

概念

线程池诞生的原因: Thread 过于强大,无法管控线程数量。

如果某个对象创建和销毁代价比较高,同时这个对象还可以反复使用的,就需要一个池子

保存多个这样的对象,需要用的时候从池子里面获取;用完之后不用销毁,放回池子;(享元模式)

节约资源提升性能;此外,还能管控总数量,防止滥用;

线程池启动线程的方法

方法一

ThreadPool.QueueUserWorkItem(

o=> this.DoSomethingLong("btnThreadPool_Click1"));

方法二

ThreadPool.QueueUserWorkItem(

o=> this.DoSomethingLong("btnThreadPool_Click2"), "嘿嘿");

获取线程池线程数量

  获取线程池最大线程数量

ThreadPool.GetMaxThreads(out int workerThreads, out int completionPortThreads);

  获取线程池最小线程数量

ThreadPool.GetMinThreads(out intworkerThreadsMin, out int completionPortThreadsMin);

设置线程池最大线程数量

ThreadPool.SetMaxThreads(8, 8);//设置的最大值,必须大于CPU核数,否则设置无效

设置线程池最小线程数量

ThreadPool.SetMinThreads(2, 2);

注意:这里设置的线程池线程数量是全局的,在设置的时候请一定小心处理

例如你设置的最大线程是8,那么在你的整个项目,只能并发运行8个线程。

线程池设置线程等待

  ManualResetEvent mre = new ManualResetEvent(false);

  //false---关闭---Set打开---true---WaitOne就能通过

  //true---打开--ReSet关闭---false--WaitOne就只能等待

  ThreadPool.QueueUserWorkItem(o =>

  {

      this.DoSomethingLong("btnThreadPool_Click1");

      mre.Set();

  });

  mre.WaitOne();

  Console.WriteLine("任务已经完成了。。。");

以下是完整的代码示例

        //ThreadPool 
        /// <summary>
        /// 
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void button1_Click(object sender, EventArgs e)
        {


            #region 启动线程池
            //启动ThreadPool方式一
            ThreadPool.QueueUserWorkItem(s => Console.WriteLine("button1_Click"));
            //启动ThreadPool方式二
            ThreadPool.QueueUserWorkItem(s => Console.WriteLine("button1_Click"), "嘿嘿");
            #endregion

            #region 获取线程池线程最大最小值
            ThreadPool.GetMaxThreads(out int workerThreads, out int completionPortThreads);
            Console.WriteLine($"当前计算机最大workerThreads是{workerThreads},最大completionPortThreads是{completionPortThreads}");

            ThreadPool.GetMinThreads(out int workerThreadsMini, out int completionPortThreadsMini);
            Console.WriteLine($"当前计算机最小workerThreadsMini是{workerThreadsMini},最小completionPortThreadsMini是{completionPortThreadsMini}");
            #endregion

            #region 设置线程池线程数(最大最小),设置的线程池数量是进程全局的,
            //委托异步调用--Task--Parrallel--async/await 全部都是线程池的线程
            //如果设置的线程数量最大值小于当前计算机的最小值,则不生效。
            ThreadPool.SetMaxThreads(8, 8);
            ThreadPool.GetMaxThreads(out int workerThreads, out int completionPortThreads);
            Console.WriteLine($"当前计算机最大workerThreads是{workerThreads},最大completionPortThreads是{completionPortThreads}");

            ThreadPool.SetMinThreads(1, 1);
            ThreadPool.GetMinThreads(out int workerThreadsMini, out int completionPortThreadsMini);
            Console.WriteLine($"当前计算机最小workerThreadsMini是{workerThreadsMini},最小completionPortThreadsMini是{completionPortThreadsMini}");
            #endregion


            #region 设置线程池线程等待
            ManualResetEvent manualReset = new ManualResetEvent(false);
            ////false---关闭---Set打开---true---WaitOne就能通过
            ////true---打开--ReSet关闭---false--WaitOne就只能等待
            ThreadPool.QueueUserWorkItem(s =>
            {
                this.DoSomethingLong("button1_Click");
                manualReset.Set();
            });
            manualReset.WaitOne();
            Console.WriteLine("等待之后做的事情");

            #endregion

        }
        #region Private Method
        /// <summary>
        /// 一个比较耗时耗资源的私有方法
        /// </summary>
        /// <param name="name"></param>
        private void DoSomethingLong(string name)
        {
            Console.WriteLine($"****************DoSomethingLong Start  {name} " +
                $" {Thread.CurrentThread.ManagedThreadId.ToString("00")} " +
                $"{DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff")}***************");
            long lResult = 0;
            for (int i = 0; i < 1_000_000_000; i++)
            {
                lResult += i;
            }
            //Thread.Sleep(2000);

            Console.WriteLine($"****************DoSomethingLong   End  {name} " +
                $" {Thread.CurrentThread.ManagedThreadId.ToString("00")} " +
                $"{DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff")} " +
                $"{lResult}***************");
        }
        #endregion
原文地址:https://www.cnblogs.com/JohnTang/p/10991807.html