示例
using Amib.Threading; using System; using System.Collections.Concurrent; using System.Collections.Generic; using System.Diagnostics; using System.Linq; using System.Text; using System.Threading; namespace SmartThreadPoolDemo { class Program { // SmartThreadPool网址 https://github.com/amibar/SmartThreadPool static void Main(string[] args) { #region 这个例子将演示传入数个参数并且等待运行然后传出的全过程 /* SmartThreadPool特性如下: 池中的线程数量会根据负载自动增减 任务异步执行后可以返回值 处于任务队列中未执行的任务可以取消 回调函数可以等待多个任务都执行完成后再触发 任务可以有优先级(priority) 任务可以分组 支持泛型Action和 Func */ SmartThreadPool stp = new SmartThreadPool(); IWorkItemResult<string> resultCallback = stp.QueueWorkItem( new Func<string, string, string>(GetResultstring), "hello ", "world" ); var stopWtch = new Stopwatch(); stopWtch.Start(); Console.WriteLine("操作开始..."); stp.Start(); stp.WaitForIdle();//等待该实例下的所有结果返回 Console.WriteLine(resultCallback.Result); stopWtch.Stop(); Console.WriteLine("操作结束,耗时 {0}", stopWtch.ElapsedMilliseconds); stp.Shutdown(); #endregion #region 这个例子将演示一批参数的传入一批线程并且等待执行结束返回值 SmartThreadPool stp2 = new SmartThreadPool(); List有性能监测机制 t_lResultItem = new List ();//不对IWorkItemResult定义其类型,其结果需要自己做类型转换 for (int i = 0; i < 100; i++) { t_lResultItem.Add(stp2.QueueWorkItem( new WorkItemCallback(GetObjectString), new string[] { "hello ", i.ToString() })); } stp2.Start(); //等待所需的结果返回 if (SmartThreadPool.WaitAll(t_lResultItem.ToArray())) { foreach (IWorkItemResult t in t_lResultItem) { Console.WriteLine("{0} : {1}", t.State, t.Result); } } #endregion #region 这个例子将演示处理线程执行过程中出现的错误 SmartThreadPool stp3 = new SmartThreadPool();//如果需要将线程池设置为调用start的时候才运行,需要设置其StartSuspended参数为true,然后为其调用start方法来启动 IWorkItemResult<double> ret = stp3.QueueWorkItem( new Func<double, double, double>(Diverse), 10, 0); //接收错误的句柄 stp3.Start(); double resule = ret.GetResult(out Exception e);//在取出结果的时候判断是否有错误产生 if (e != null) { //在这里进行错误处理,错误在InnerException中 Console.WriteLine("产生错误:" + e.InnerException.Message); } else { Console.WriteLine(resule.ToString()); } stp3.Shutdown(); #endregion #region 方法属性解释 //SmartThreadPool的部分解释 SmartThreadPool smartThreadPool = new SmartThreadPool(); //获取当前线程池中的工作线程数,与InUseThreads可能会有差别,因为InUseThreads不包含Idle状态的线程 int threadNum = smartThreadPool.ActiveThreads; //取消所有工作项,如果工作项在执行,那么等待工作项执行完 smartThreadPool.Cancel(); //如果不想等待工作项执行完, smartThreadPool.Cancel(true); //线程池的最大并发数,即MaxWorkerThreads, //如果修改后的Concurrency小于MinWorkerThreads,那么MinWorkerThreads也会随之改变 smartThreadPool.Concurrency = 25; //创建一个工作组,最大并发为3,工作组在后面会详细说明, smartThreadPool.CreateWorkItemsGroup(3); //卸载线程池 smartThreadPool.Dispose(); //反回所有未执行的工作项的参数对象 smartThreadPool.GetStates(); //获取线程池中正在工作的线程数,与ActiveThreads会有差别,因为ActiveThreads可能包含Idle状态的线程 int useThreadNum = smartThreadPool.InUseThreads; //当线程池用没有工作项时,反回true,否则,反回false bool IsIdle = smartThreadPool.IsIdle; //同时并行执行多个方法,并且阻塞到所有工作项都执行完,这里会有多少个工作项就会创造多少个线程, smartThreadPool.Join(new Action[] { new Action(Test1) }); //获取或设置最大线程数,即MaxWorkerThreads, smartThreadPool.MaxThreads = 25; //最小线程数,当没有工作项时,线程池最多剩余的线程数 smartThreadPool.MinThreads = 0; //线程池的名称,没什么特殊的用处, smartThreadPool.Name = "StartThreadPool"; //当线程池中没有工作项(即闲置)时触发的事件 smartThreadPool.OnIdle += new WorkItemsGroupIdleHandler(smartThreadPool_OnIdle); //当线程池启动一个线程时,触发的事件 smartThreadPool.OnThreadInitialization += new ThreadInitializationHandler(smartThreadPool_OnThreadInitialization); //当线程池释放一个线程时,所触发的事件 smartThreadPool.OnThreadTermination += new ThreadTerminationHandler(smartThreadPool_OnThreadTermination); //与Join方法类似,并行执行多个带参数的方法,这里会有多少个工作项就会创造多少个线程 smartThreadPool.Pipe<object>(new object(), new Action<object>[] { new Action<object>(Test) }); //卸载线程池 smartThreadPool.Shutdown(); //启动线程池 smartThreadPool.Start(); //STPStartInfo对象的只读实例 STPStartInfo stpStartInfo = smartThreadPool.STPStartInfo; //等待所有的工作项执行完成(即IsIdle为true) smartThreadPool.WaitForIdle(); //获取还未执行的工作项数量 int wiNum = smartThreadPool.WaitingCallbacks; //WorkItemGroup的启动信息的只读实力 WIGStartInfo wigStartInfo = smartThreadPool.WIGStartInfo; #endregion #region 简单调用实例 //****************************使用示例**************************** //创建一个线程池 smartThreadPool = new SmartThreadPool(); //执行任务 smartThreadPool.QueueWorkItem(() => { Console.WriteLine("Hello World!"); }); //****************************分割线**************************** //创建一个线程池 带返回值的任务 smartThreadPool = new SmartThreadPool(); //执行任务 var result = smartThreadPool.QueueWorkItem(() => { var sum = 0; for (var i = 0; i < 10; i++) { sum += i; } return sum; }); Console.WriteLine(result.Result); //输出计算结果 //****************************分割线**************************** // 创建一个线程池 等待多个任务执行完成 smartThreadPool = new SmartThreadPool(); // 执行任务 var result1 = smartThreadPool.QueueWorkItem(() => { //模拟计算较长时间 Thread.Sleep(5000); return 3; }); var result2 = smartThreadPool.QueueWorkItem(() => { //模拟计算较长时间 Thread.Sleep(3000); return 5; }); bool success = SmartThreadPool.WaitAll(new IWorkItemResult<int>[] { result1, result2 }); if (success) { //输出结果 Console.WriteLine(result1.Result); Console.WriteLine(result2.Result); } Console.ReadLine(); #endregion Test(); } #region 事件 private static void Test1() { } private static void Test(object obj) { } private static void smartThreadPool_OnThreadTermination() { } private static void smartThreadPool_OnThreadInitialization() { } private static void smartThreadPool_OnIdle(IWorkItemsGroup workItemsGroup) { } #endregion static Random _random = new Random(); /// /// 类似 易语言的写法 可能会出现 bug /// private static void Test() { var idleCount = 0; var workingCount = 0; var queueWorkCount = 0; var job = new ConcurrentQueue<int>(); for (int i = 0; i < 100; i++) job.Enqueue(i);//模拟1000个任务 #region 只投递空闲线程数 var smartThreadPool = new SmartThreadPool(new STPStartInfo { MinWorkerThreads = 1, //最小线程数 MaxWorkerThreads = 10, //最大线程数 AreThreadsBackground = true, //设置为后台线程 }); #region 手动释放写法 while (true) { idleCount = smartThreadPool.MaxThreads - smartThreadPool.InUseThreads;//最大线程数 减去 正在执行的线程数 等于 空闲线程数 if (idleCount <= 0) { smartThreadPool.WaitForIdle(1000); continue; } if (job.Count <= 0)//剩下任务数为0 { if (smartThreadPool.IsIdle)//判断是否空闲 break; smartThreadPool.WaitForIdle(1000); continue; } if (job.Count > idleCount) workingCount = idleCount; else workingCount = job.Count; for (int i = 0; i < workingCount; i++) { queueWorkCount++; smartThreadPool.QueueWorkItem(() => { job.TryDequeue(out int result); Thread.Sleep(_random.Next(10000));//模拟工作耗时 }); } if (queueWorkCount > 10)//模拟拨号 { smartThreadPool.WaitForIdle();//等待所有任务执行完毕 // adsl拨号程序 Console.WriteLine("adsl"); Thread.Sleep(_random.Next(5000));//模拟拨号 queueWorkCount = 0; } smartThreadPool.WaitForIdle(1000); } smartThreadPool.Shutdown(); smartThreadPool.Dispose(); #endregion #region 自动释放写法 using (smartThreadPool = new SmartThreadPool(new STPStartInfo { MinWorkerThreads = 1, //最小线程数 MaxWorkerThreads = 10, //最大线程数 AreThreadsBackground = true, //设置为后台线程 })) { while (true) { idleCount = smartThreadPool.MaxThreads - smartThreadPool.InUseThreads;//最大线程数 减去 正在执行的线程数 等于 空闲线程数 if (idleCount <= 0) { smartThreadPool.WaitForIdle(1000); continue; } if (job.Count <= 0)//剩下任务数为0 { if (smartThreadPool.IsIdle)//判断是否空闲 break; smartThreadPool.WaitForIdle(1000); continue; } if (job.Count > idleCount) workingCount = idleCount; else workingCount = job.Count; for (int i = 0; i < workingCount; i++) { queueWorkCount++; smartThreadPool.QueueWorkItem(() => { job.TryDequeue(out int result); Thread.Sleep(_random.Next(10000));//模拟工作耗时 }); } if (queueWorkCount > 10)//模拟拨号 { smartThreadPool.WaitForIdle();//等待所有任务执行完毕 // adsl拨号程序 Console.WriteLine("adsl"); Thread.Sleep(_random.Next(5000));//模拟拨号 queueWorkCount = 0; } smartThreadPool.WaitForIdle(1000); } } #endregion #endregion #region 投递所有任务 using (smartThreadPool = new SmartThreadPool(new STPStartInfo { MinWorkerThreads = 1, //最小线程数 MaxWorkerThreads = 10, //最大线程数 AreThreadsBackground = true, //设置为后台线程 })) { for (int i = 0; i < job.Count; i++) { smartThreadPool.QueueWorkItem(() => { job.TryDequeue(out int result); Thread.Sleep(_random.Next(10000));//模拟工作耗时 }); } smartThreadPool.WaitForIdle();//等待所有任务执行完毕 } #endregion } private static string GetResultstring(string str, string str2) { string result = ""; for (int i = 0; i < 20; i++) { System.Threading.Thread.Sleep(200); result += i + ","; } return str + str2 + result.TrimEnd(','); } private static object GetObjectString(object obj) { return string.Format("{0}{1}", (obj as string[])[0], (obj as string[])[1]); } private static double Diverse(double x, double y) { return x / y; } } }