.NetFramework1.0时代的Thread,API功能繁多,对线程的数量是没有管控的,在.NetFramework2.0时代推出了ThreadPool,若是某个对象建立和销毁代价比较高,同时这个对象还能够反复使这些线程,就须要使用线程池,线程池能够保存多个线程对象,须要使用线程时直接从线程池里面拿,使用完以后不作释放,又放回池子(享元模式),须要用的时候再去拿。这样能够减小建立线程的开销,提高性能,此外,还能够管控线程的总数量,防止资源滥用。数组
委托异步调用、Task、Parrallel、async/await的线程所有都是线程池里面的线程。直接new Thread开起的线程不受线程池的数量限制(可是会占用线程池的线程数量)。异步
ThreadPool.QueueUserWorkItem(o=>this.DoSomeThing("btnThreadPool_Click_1")); ThreadPool.QueueUserWorkItem(o => { this.DoSomeThing("btnThreadPool_Click_2"); Console.WriteLine( o?.ToString()); }, "wjl");
I/O线程是.NET专为访问外部资源所设置的一种线程,由于访问外部资源经常要受到外界因素的影响,为了防止让主线程受影响而长期处于阻塞状态,.NET为多个I/O操做都创建起了异步方法。async
//检索由 GetMaxThreads 返回的线程池线程的最大数目和异步IO线程的最大数目 ThreadPool.GetMaxThreads(out int workerThreads, out int completionPortThreads); Console.WriteLine($"当前线程池最大数目为:{workerThreads},最大异步IO线程:{completionPortThreads}"); //检索由 GetMinThreads 返回的线程池线程的最小数目和异步IO线程的最小数目 ThreadPool.GetMinThreads(out int workerThreadsMin, out int completionPortThreadsMin); Console.WriteLine($"当前线程池最小数目为:{workerThreadsMin},最小异步IO线程:{completionPortThreadsMin}"); ThreadPool.SetMaxThreads(8, 8);//设置的最大值,必须大于CPU核数,不然设置无效 ThreadPool.SetMinThreads(2, 2);
单个线程等待:函数
//线程等待 ManualResetEvent mre = new ManualResetEvent(false); //ManualResetEvent是一种信号量的方式 //若是初始为false--关闭, mre.Set()以后变为ture,WaitOne就能经过 //若是初始为tue--打开, mre.Rset()以后变为false,WaitOne就只能等待 ThreadPool.QueueUserWorkItem(o => { this.DoSomeThing("btnThreadPool_Click_3"); mre.Set(); }); mre.WaitOne(); Console.WriteLine("任务已经完成了...");
多个线程等待:性能
ManualResetEvent[] mres = new ManualResetEvent[10]; for (int i = 0; i < 10; i++) { mres[i] = new ManualResetEvent(false); int k = i; ThreadPool.QueueUserWorkItem(o => { this.DoSomeThing($"mres{k}"); ManualResetEvent mre = o as ManualResetEvent; mre.Set(); }, mres[i]); } //等待全部数组中的元素都收到信号,若是是控制台程序或者winform程序,请将Main()函数上面的特性[STAThread]注释掉 WaitHandle.WaitAll(mres); Console.WriteLine("多个任务已经完成了...");