C# ThreadPool类(线程池)

地址:https://www.cnblogs.com/scmail81/archive/2018/08/19/9503266.htmlhtml

 

 

CLR线程池并不会在CLR初始化时当即创建线程,而是在应用程序要建立线程来运行任务时,线程池才初始化一个线程。
线程池初始化时是没有线程的,线程池里的线程的初始化与其余线程同样,可是在完成任务之后,该线程不会自行销毁,而是以挂起的状态返回到线程池。直到应用程序再次向线程池发出请求时,线程池里挂起的线程就会再度激活执行任务。
这样既节省了创建线程所形成的性能损耗,也可让多个任务反复重用同一线程,从而在应用程序生存期内节约大量开销。网络

经过CLR线程池所创建的线程老是默认为后台线程,优先级数为ThreadPriority.Normal。ide

CLR线程池分为工做者线程(workerThreads)I/O线程(completionPortThreads)两种:函数

  • 工做者线程是主要用做管理CLR内部对象的运做,一般用于计算密集的任务。
  • I/O(Input/Output)线程主要用于与外部系统交互信息,如输入输出,CPU仅需在任务开始的时候,将任务的参数传递给设备,而后启动硬件设备便可。等任务完成的时候,CPU收到一个通知,通常来讲是一个硬件的中断信号,此时CPU继续后继的处理工做。在处理过程当中,CPU是没必要彻底参与处理过程的,若是正在运行的线程不交出CPU的控制权,那么线程也只能处于等待状态,即便操做系统将当前的CPU调度给其余线程,此时线程所占用的空间仍是被占用,而并无CPU处理这个线程,可能出现线程资源浪费的问题。若是这是一个网络服务程序,每个网络链接都使用一个线程管理,可能出现大量线程都在等待网络通讯,随着网络链接的不断增长,处于等待状态的线程将会很消耗尽全部的内存资源。能够考虑使用线程池解决这个问题。

  线程池的最大值通常默认为1000、2000。当大于此数目的请求时,将保持排队状态,直到线程池里有线程可用。性能

  使用CLR线程池的工做者线程通常有两种方式:测试

  • 经过ThreadPool.QueueUserWorkItem()方法;
  • 经过委托;

  要注意,不管是经过ThreadPool.QueueUserWorkItem()仍是委托,调用的都是线程池里的线程。优化

经过如下两个方法能够读取和设置CLR线程池中工做者线程与I/O线程的最大线程数。spa

  1. ThreadPool.GetMax(out in workerThreads,out int completionPortThreads);
  2. ThreadPool.SetMax(int workerThreads,int completionPortThreads);

  若想测试线程池中有多少线程正在投入使用,能够经过ThreadPool.GetAvailableThreads(out in workThreads,out int conoletionPortThreads)方法。操作系统

方法 说明
GetAvailableThreads 剩余空闲线程数
GetMaxThreads 最多可用线程数,全部大于此数目的请求将保持排队状态,直到线程池线程变为可用
GetMinThreads 检索线程池在新请求预测中维护的空闲线程数
QueueUserWorkItem 启动线程池里得一个线程(队列的方式,如线程池暂时没空闲线程,则进入队列排队)
SetMaxThreads 设置线程池中的最大线程数
SetMinThreads 设置线程池最少须要保留的线程数

咱们可使用线程池来解决上面的大部分问题,跟使用单个线程相比,使用线程池有以下优势:线程

一、缩短应用程序的响应时间。由于在线程池中有线程的线程处于等待分配任务状态(只要没有超过线程池的最大上限),无需建立线程。

二、没必要管理和维护生存周期短暂的线程,不用在建立时为其分配资源,在其执行完任务以后释放资源。

三、线程池会根据当前系统特色对池内的线程进行优化处理。

总之使用线程池的做用就是减小建立和销毁线程的系统开销。在.NET中有一个线程的类ThreadPool,它提供了线程池的管理。

ThreadPool是一个静态类,它没有构造函数,对外提供的函数也所有是静态的。其中有一个QueueUserWorkItem方法,它有两种重载形式,以下:

public static bool QueueUserWorkItem(WaitCallback callBack):将方法排入队列以便执行。此方法在有线程池线程变得可用时执行。

public static bool QueueUserWorkItem(WaitCallback callBack,Object state):将方法排入队列以便执行,并指定包含该方法所用数据的对象。此方法在有线程池线程变得可用时执行。

QueueUserWorkItem方法中使用的的WaitCallback参数表示一个delegate,它的声明以下:

public delegate void WaitCallback(Object state)

若是须要传递任务信息能够利用WaitCallback中的state参数,相似于ParameterizedThreadStart委托。

下面是一个ThreadPool的例子,代码以下:

复制代码
using System;
using System.Collections;
using System.ComponentModel;
using System.Diagnostics;
using System.Threading;

namespace ConsoleApp1
{
    class ThreadPoolDemo
    {
        public ThreadPoolDemo()
        {
        }

        public void Work()
        {
            ThreadPool.QueueUserWorkItem(new WaitCallback(CountProcess));
            ThreadPool.QueueUserWorkItem(new WaitCallback(GetEnvironmentVariables));
        }
        /// <summary>  
        /// 统计当前正在运行的系统进程信息  
        /// </summary>  
        /// <param name="state"></param>  
        private void CountProcess(object state)
        {
            Process[] processes = Process.GetProcesses();
            foreach (Process p in processes)
            {
                try
                {
                    Console.WriteLine("进程信息:Id:{0},ProcessName:{1},StartTime:{2}", p.Id, p.ProcessName, p.StartTime);
                }
                catch (Win32Exception e)
                {
                    Console.WriteLine("ProcessName:{0}", p.ProcessName);
                }
                finally
                {
                }
            }
            Console.WriteLine("获取进程信息完毕。");
        }
        /// <summary>  
        /// 获取当前机器系统变量设置  
        /// </summary>  
        /// <param name="state"></param>  
        public void GetEnvironmentVariables(object state)
        {
            IDictionary list = System.Environment.GetEnvironmentVariables();
            foreach (DictionaryEntry item in list)
            {
                Console.WriteLine("系统变量信息:key={0},value={1}", item.Key, item.Value);
            }
            Console.WriteLine("获取系统变量信息完毕。");
        }
    }
}
复制代码
复制代码
using System;
using System.Threading;

namespace ConsoleApp1
{

    class Program
    {
        static void Main(string[] args)
        {
            ThreadPoolDemo tpd1 = new ThreadPoolDemo();
            tpd1.Work();
            Thread.Sleep(5000);
            Console.WriteLine("OK");
            Console.ReadLine();
        }
    }
}
复制代码
相关文章
相关标签/搜索