概念
线程池诞生的原因: 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