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)
{ }
C# 执行固定个数任务自行控制进入线程池的线程数量,多任务同时但是并发数据限定的更多相关文章
- 由浅入深理解Java线程池及线程池的如何使用
前言 多线程的异步执行方式,虽然能够最大限度发挥多核计算机的计算能力,但是如果不加控制,反而会对系统造成负担.线程本身也要占用内存空间,大量的线程会占用内存资源并且可能会导致Out of Memory ...
- Java多线程、线程池和线程安全整理
多线程 1.1 多线程介绍 进程指正在运行的程序.确切的来说,当一个程序进入内存运行,即变成一个进程,进程是处于运行过程中的程序,并且具有一定独立功能. 1.2 Thread类 通 ...
- Java多线程系列 JUC线程池03 线程池原理解析(二)
转载 http://www.cnblogs.com/skywang12345/p/3509954.html http://www.cnblogs.com/skywang12345/p/351294 ...
- Java多线程系列 JUC线程池02 线程池原理解析(一)
转载 http://www.cnblogs.com/skywang12345/p/3509960.html ; http://www.cnblogs.com/skywang12345/p/35099 ...
- Java多线程系列 JUC线程池01 线程池框架
转载 http://www.cnblogs.com/skywang12345/p/3509903.html 为什么引入Executor线程池框架 new Thread()的缺点 1. 每次new T ...
- 异步线程编程,线程池,线程组,后面涉及ThreadLocal在理解
join模拟订单 package com.future.demo.future; /** * * * @author Administrator * */ public class NormalThr ...
- java并发编程(十五)----(线程池)java线程池简介
好的软件设计不建议手动创建和销毁线程.线程的创建和销毁是非常耗 CPU 和内存的,因为这需要 JVM 和操作系统的参与.64位 JVM 默认线程栈是大小1 MB.这就是为什么说在请求频繁时为每个小的请 ...
- 多线程、线程池、线程创建、Thread
转载自https://www.cnblogs.com/jmsjh/p/7762034.html 多线程 1.1 多线程介绍 学习多线程之前,我们先要了解几个关于多线程有关的概念. 进程:进程指正在运行 ...
- java 线程池(线程的复用)
一. 线程池简介 1. 线程池的概念: 线程池就是首先创建一些线程,它们的集合称为线程池.使用线程池可以很好地提高性能,线程池在系统启动时即创建大量空闲的线程,程序将一个任务传给线程池,线程池就会启动 ...
随机推荐
- [洛谷P4723]【模板】线性递推
题目大意:求一个满足$k$阶齐次线性递推数列$a_i$的第$n$项. 即:$a_n=\sum\limits_{i=1}^{k}f_i \times a_{n-i}$ 题解:线性齐次递推,先见洛谷题解, ...
- 纯css实现长宽等比例的div
现代网站页面基本都需要响应式,一个div的长宽往往我们都设置为百分之多少,这个百分之是相对于父容器动态计算的 这样在浏览器宽度变化之后,我们的元素也能自动更新长宽.例如:我们在页面上摆了一个div,这 ...
- [UVA 10635] Prince ans Princess
图片加载可能有点慢,请跳过题面先看题解,谢谢 这道题... 还是要点思维的... 第一眼看是个最长公共子序列,但是, \(N\le 62500\) ,并不能 \(O(n^2)\) 求 $ $ 这道题有 ...
- 【树论 2】Kruskal 的学习和使用
Tips:本题解是[随便搞搞 1]Prim算法的学习和使用 的姊妹篇,希望先阅读Prim算法. 预习及预备知识: 克鲁斯卡尔(Kruskal)算法是实现图的最小生成树最常用的算法. 大家知道,存储图的 ...
- 【BZOJ2731】三角形覆盖问题
想象一条平行于\(y\)轴的扫描线,从低往高扫描.如何确定关键高度才能使每两个关键高度之间分割出的图形易于计算呢? 关键高度有:三角形底边高度.三角形上顶点高度.三角形交点的高度. 如此分割,我们 ...
- 洛谷 P1783 海滩防御 解题报告
P1783 海滩防御 题目描述 WLP同学最近迷上了一款网络联机对战游戏(终于知道为毛JOHNKRAM每天刷洛谷效率那么低了),但是他却为了这个游戏很苦恼,因为他在海边的造船厂和仓库总是被敌方派人偷袭 ...
- Codeforces 901C. Bipartite Segments(思维题)
擦..没看见简单环..已经想的七七八八了,就差一步 显然我们只要知道一个点最远可以向后扩展到第几个点是二分图,我们就可以很容易地回答每一个询问了,但是怎么求出这个呢. 没有偶数简单环,相当于只有奇数简 ...
- MVC 中@Html.DropDownListFor() 设置选中项 这么不好使 ? [问题点数:40分,结帖人lkf181]
http://bbs.csdn.net/topics/390867060 由于不知道错误原因在哪 我尽量把代码都贴出来吧:重点是:在 Controller 类里 我给 SelectListItem集合 ...
- C标准库函数--文件IO操作函数。
C标准库文件读写函数总结:都是对文件流进行输入输出的函数分为对文件的有格式读写以及无格式读写 一.文件的无格式读写根据每次读写字符的数量,分为三类:1.按字符读写文件 按字符读有三个函数:以下三个函数 ...
- 八、java常用类
目录 一.字符串相关类 String类 StringBuffer类 二.基本数据类型包装类 三.Math类 四.File类 五.枚举类 一.字符串相关类 1.String类 java.lang.Str ...