C# 执行固定个数任务自行控制进入线程池的线程数量,多任务同时但是并发数据限定
思路来源:http://bbs.csdn.NET/topics/390819824,引用该页面某网友提供的方法。
题目:我现在有100个任务,需要多线程去完成,但是要限定同时并发数量不能超过5个。
原理:初始启用5个线程,然后让线程中的过程执行完毕之后,自己去取下一个任务,启动下一个线程。
- public class MyTaskList
- {
- public List<Action> Tasks = new List<Action>();
- public void Start()
- {
- for (var i = 0; i < 5; i++)
- StartAsync();
- }
- public event Action Completed;
- public void StartAsync()
- {
- lock (Tasks)
- {
- if (Tasks.Count > 0)
- {
- var t = Tasks[Tasks.Count - 1];
- Tasks.Remove(t);
- ThreadPool.QueueUserWorkItem(h =>
- {
- t();
- StartAsync();
- });
- }
- else if (Completed != null)
- Completed();
- }
- }
- }
public class MyTaskList { public List<Action> Tasks = new List<Action>(); public void Start() { for (var i = 0; i < 5; i++) StartAsync(); } public event Action Completed; public void StartAsync() { lock (Tasks) { if (Tasks.Count > 0) { var t = Tasks[Tasks.Count - 1]; Tasks.Remove(t); ThreadPool.QueueUserWorkItem(h => { t(); StartAsync(); }); } else if (Completed != null) Completed(); } } }调用方式:
1,自动加入的100个测试任务,每一个运行时间都是不定的、随机的。
2,这里的 StartAsync 方法瞬间就结束了,根本不会阻塞,也不会等待什么 while 循环结束
- var rnd = new Random();
- var lst = new MyTaskList();
- for (var i = 0; i < 100; i++)
- {
- var s = rnd.Next(10);
- var j = i;
- var 测试任务 = new Action(() =>
- {
- Console.WriteLine(string.Format("第{0}个任务(用时{1}秒)已经开始", j, s));
- Thread.Sleep(s * 1000);
- Console.WriteLine(string.Format("第{0}个任务(用时{1}秒)已经结束", j, s));
- });
- lst.Tasks.Add(测试任务);
- }
- lst.Completed += () => Console.WriteLine("____________________没有更多的任务了!");
- lst.Start();
var rnd = new Random(); var lst = new MyTaskList(); for (var i = 0; i < 100; i++) { var s = rnd.Next(10); var j = i; var 测试任务 = new Action(() => { Console.WriteLine(string.Format("第{0}个任务(用时{1}秒)已经开始", j, s)); Thread.Sleep(s * 1000); Console.WriteLine(string.Format("第{0}个任务(用时{1}秒)已经结束", j, s)); }); lst.Tasks.Add(测试任务); } lst.Completed += () => Console.WriteLine("____________________没有更多的任务了!"); lst.Start();
自己使用到程序中,自定义最大线程数,然后循环启用最大线程数个线程执行任务,等待有线程完成,退出本次运行方法和线程前,再次调用启用线程方法调用下一个线程,依次循环,直至完成:
- AutoResetEvent[] waitEnents = new AutoResetEvent[n_max_thread];
- for (int i = 0; i < n_max_thread; i++)
- {
- calcState.wait_event = waitEnents[i] = new AutoResetEvent(false);
- StartAsync(calcState);
- }
- AutoResetEvent.WaitAll(waitEnents);
- private static void StartAsync(CalcState calcState)
- {
- lock (calcState.locker_ListFormula)
- {
- if (calcState.lstFormula.Count > 0)
- {
- calcState.formulaAttr = calcState.lstFormula.ElementAt(calcState.lstFormula.Count - 1).Value;
- calcState.lstFormula.Remove(calcState.lstFormula.ElementAt(calcState.lstFormula.Count - 1).Key);
- ThreadPool.QueueUserWorkItem(new WaitCallback(ExecAsync), calcState);
- }
- else
- {
- calcState.wait_event.Set();
- }
- }
- }
- private static void ExecAsync(object obj)
- {
- CalcState calcState = obj as CalcState;
- startCalcFormula(calcState);
- //递归处理下一个公式
- StartAsync(calcState);
- }
- private static void startCalcFormula(CalcState calcState)
- {
- }
AutoResetEvent[] waitEnents = new AutoResetEvent[n_max_thread]; for (int i = 0; i < n_max_thread; i++) { calcState.wait_event = waitEnents[i] = new AutoResetEvent(false); StartAsync(calcState); } AutoResetEvent.WaitAll(waitEnents); private static void StartAsync(CalcState calcState) { lock (calcState.locker_ListFormula) { if (calcState.lstFormula.Count > 0) { calcState.formulaAttr = calcState.lstFormula.ElementAt(calcState.lstFormula.Count - 1).Value; calcState.lstFormula.Remove(calcState.lstFormula.ElementAt(calcState.lstFormula.Count - 1).Key); ThreadPool.QueueUserWorkItem(new WaitCallback(ExecAsync), calcState); } else { calcState.wait_event.Set(); } } } private static void ExecAsync(object obj) { CalcState calcState = obj as CalcState; startCalcFormula(calcState); //递归处理下一个公式 StartAsync(calcState); } private static void startCalcFormula(CalcState calcState) { }