zoukankan      html  css  js  c++  java
  • 异步多线程(三)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
  • 相关阅读:
    转:[Silverlight入门系列]使用MVVM模式(9): 想在ViewModel中控制TreeView节点展开?
    C#线程同步方法——Monitor
    转:Mongodb源码分析之Replication模式
    转:Mysql使用主从复制机制(replication)
    Ruby IDE
    转:ASP.NET MVC4细嚼慢咽---(5)js css文件合并
    转:ASP.NET MVC4细嚼慢咽---(6)全局过滤器
    转:WCF服务开发与调用的完整示例
    转:WF工作流技术内幕 —— 通过Web服务调用Workflow工作流(开发持久化工作流)
    汇总高效的卷积神经网络结构[转载]
  • 原文地址:https://www.cnblogs.com/JohnTang/p/10991807.html
Copyright © 2011-2022 走看看