Task+ConcurrentQueue多线程编程
队列(Queue)代表了一个先进先出的对象集合。当您需要对各项进行先进先出的访问时,则使用队列。当您在列表中添加一项,称为入队,当您从列表中移除一项时,称为出队。
ConcurrentQueue<T>队列是一个高效的线程安全的队列,是.Net Framework 4.0,System.Collections.Concurrent命名空间下的一个数据结构。
Task是在ThreadPool的基础上推出的,我们知道了ThreadPool的弊端:我们不能控制线程池中线程的执行顺序,也不能获取线程池内线程取消/异常/完成的通知。net4.0在ThreadPool的基础上推出了Task,Task拥有线程池的优点,同时也解决了使用线程池不易控制的弊端。
下面我们来看下Task+ConcurrentQueue实现多线程编程
1、定义最大线程数, 一般和本机的cpu 有关
/// <summary>
/// 线程总数
/// </summary>
private int threadNum = Convert.ToInt32(ConfigurationManager.AppSettings["ThreadNum"]);
ConcurrentQueue队列
/// <summary>
/// 队列
/// </summary>
private ConcurrentQueue<AssetRepayment> queues = new ConcurrentQueue<AssetRepayment>();
2、接下来 我们把业务数据取出来,加到定义的 queues.Enqueue(l);
var dt = DateTime.Now.Date;
var list = AssetRepayService.GetRepayments().Where(o => o.AssetRepayStatus == AssetRepayStatus.NoSend && o.PlanRepaymentDate == dt && o.AssetRepayMode == AssetRepayMode.Withholding);
int count = list.Count();
if (count == 0)
{
LogHelper.WriteFatal("代扣充值-没有可执行的数据");
return;
}
totalCount = count;
int allpage = count / 200 + (count % 200 == 0 ? 0 : 1);
int page = 0;
LogHelper.WriteFatal("代扣充值-可执行的数据:" + count + "条,页数:"+ allpage); do
{
LogHelper.WriteFatal("代扣充值-第:" + page + "页"); var ll = list.OrderBy(o=>o.Id).Skip(page++ * 200).Take(200).ToList();
foreach (var l in ll)
{
queues.Enqueue(l);
}
}
while (page < allpage);
3、等数据全部加载到queues,我们接着下一步
List<Task> tasks = new List<Task>();
for (int i = 0; i < threadNum; i++)
{
var task = Task.Run(() =>
{
Process();
});
tasks.Add(task);
}
var taskList = Task.Factory.ContinueWhenAll(tasks.ToArray(), (ts) =>
{
});
taskList.Wait();
利用Task 处理数据
这里需要注意的是
var taskList = Task.Factory.ContinueWhenAll(tasks.ToArray(), (ts) =>
{
});
taskList.Wait();
这个代表开始执行线程并且需要全部完成 才会退出 ContinueWhenAll
4 接下去我们看下处理程序怎么消费数据
从队列取数据
var currentIndex = Interlocked.Increment(ref index);
AssetRepayment repayId = null;
var isExit = queues.TryDequeue(out repayId);
if (!isExit)
{
break;
}
有数据的话 往下走 执行我们要的业务逻辑
var service = context.GetService<IDeTransactionService>();
service.SubDeTransaction(repayId); LogHelper.WriteFatal(string.Format("代扣充值 共{0}条 当前第{1}条", totalCount, currentIndex));
完整处理方法如下
private void Process()
{
using (var context = new MefContext())
{
while (true)
{
var currentIndex = Interlocked.Increment(ref index);
AssetRepayment repayId = null;
var isExit = queues.TryDequeue(out repayId);
if (!isExit)
{
break;
}
try
{
var service = context.GetService<IDeTransactionService>();
service.SubDeTransaction(repayId); LogHelper.WriteFatal(string.Format("代扣充值 共{0}条 当前第{1}条", totalCount, currentIndex));
}
catch (Exception ex)
{
LogHelper.WriteError("代扣充值-", ex);
}
}
}
}
到此为止,我们实现了 Task+ConcurrentQueue多线程编程。
完整代码块
链接:https://pan.baidu.com/s/1jgpafTFssiVLmZhDe1CgYQ
提取码:erib
Task+ConcurrentQueue多线程编程的更多相关文章
- 5天玩转C#并行和多线程编程 —— 第四天 Task进阶
5天玩转C#并行和多线程编程系列文章目录 5天玩转C#并行和多线程编程 —— 第一天 认识Parallel 5天玩转C#并行和多线程编程 —— 第二天 并行集合和PLinq 5天玩转C#并行和多线程编 ...
- 5天玩转C#并行和多线程编程 —— 第三天 认识和使用Task
5天玩转C#并行和多线程编程系列文章目录 5天玩转C#并行和多线程编程 —— 第一天 认识Parallel 5天玩转C#并行和多线程编程 —— 第二天 并行集合和PLinq 5天玩转C#并行和多线程编 ...
- Scalaz(45)- concurrency :Task-函数式多线程编程核心配件
我们在上一节讨论了scalaz Future,我们说它是一个不完善的类型,最起码没有完整的异常处理机制,只能用在构建类库之类的内部环境.如果scalaz在Future类定义中增加异常处理工具的话,用户 ...
- 新手浅谈Task异步编程和Thread多线程编程
初学Task的时候上网搜索,看到很多文章的标题都是task取代thread等等相关,我也一直以为task和thread是一类,其实task是.net4.0提出的异步编程,在之前.net1.0有dele ...
- C#多线程编程(1)--线程,线程池和Task
新开了一个多线程编程系列,该系列主要讲解C#中的多线程编程. 利用多线程的目的有2个: 一是防止UI线程被耗时的程序占用,导致界面卡顿:二是能够利用多核CPU的资源,提高运行效率. 我没有进行很 ...
- 转载 .Net多线程编程—任务Task https://www.cnblogs.com/hdwgxz/p/6258014.html
.Net多线程编程—任务Task 1 System.Threading.Tasks.Task简介 一个Task表示一个异步操作,Task的创建和执行是独立的. 只读属性: 返回值 名称 说明 ob ...
- .NET 4中的多线程编程之一:使用Task(转载)
原文地址:http://www.cnblogs.com/yinzixin/archive/2011/11/04/2235233.html .NET 4为了简化多线程编程,提供了System.Threa ...
- Task C# 多线程和异步模型 TPL模型 【C#】43. TPL基础——Task初步 22 C# 第十八章 TPL 并行编程 TPL 和传统 .NET 异步编程一 Task.Delay() 和 Thread.Sleep() 区别
Task C# 多线程和异步模型 TPL模型 Task,异步,多线程简单总结 1,如何把一个异步封装为Task异步 Task.Factory.FromAsync 对老的一些异步模型封装为Task ...
- 5天玩转C#并行和多线程编程 —— 第二天 并行集合和PLinq
5天玩转C#并行和多线程编程系列文章目录 5天玩转C#并行和多线程编程 —— 第一天 认识Parallel 5天玩转C#并行和多线程编程 —— 第二天 并行集合和PLinq 5天玩转C#并行和多线程编 ...
随机推荐
- 【剑指Offer】二叉搜索树的第k个结点 解题报告(Python)
[剑指Offer]二叉搜索树的第k个结点 解题报告(Python) 标签(空格分隔): 剑指Offer 题目地址:https://www.nowcoder.com/ta/coding-intervie ...
- 1235 - Coin Change (IV)
1235 - Coin Change (IV) PDF (English) Statistics Forum Time Limit: 1 second(s) Memory Limit: 32 M ...
- sql注入-整数型
sql注入整数型 1.按照提示输入1,发现直接给出了SQL语句 2.使用order by判断字段数 首先使用order by 3 ,页面无回显,改为2之后页面显示正确.因此判断当前数据库当 ...
- C++中常用的数学函数总结
我们在C++程序设计的过程中往往会使用到一些数学函数,那么不同的数学运算要用到什么函数哪?大家可以参考我的总结如下: 首先引用到数学函数时一定要记得加函数头文件 #include<cmath&g ...
- 13 个 C# 10 特性
原文链接:https://blog.okyrylchuk.dev 原文作者:Oleg Kyrylchuk 译: 等天黑 常量的内插字符串 C# 10 允许使用在常量字符串初始化中使用插值, 如下 co ...
- .net core的Swagger接口文档使用教程(二):NSwag
上一篇介绍了Swashbuckle ,地址:.net core的Swagger接口文档使用教程(一):Swashbuckle 讲的东西还挺多,怎奈微软还推荐了一个NSwag,那就继续写吧! 但是和Sw ...
- Ubuntu18.04安装/卸载NVIDIA显卡驱动
1 显卡驱动下载 官网:NVIDIA 搜索适合本机的驱动 获取最新版本驱动 立即下载 文件 以上,显卡驱动下载完成. 2 显卡驱动安装 2.1 添加可执行权限 进入驱动文件目录sudo chmod a ...
- Sentry 企业级数据安全解决方案 - Relay 运行模式
内容整理自官方开发文档 Relay 可以在几种主要模式之一下运行,如果您正在配置 Relay server 而不是使用默认设置,那么事先了解这些模式至关重要. 模式存储在配置文件中,该文件包含 rel ...
- 初识python: xlsxwriter 将数据写入Excel
使用 xlsxwriter 模块将数据写入excel . #!/user/bin env python # author:Simple-Sir # time:2020/9/24 12:51 # 使用 ...
- scrollTop、scrollHeight与clientHeight
MDN上概念 scrollTop:获取或设置一个元素的内容垂直滚动的像素数. scrollHeight:一个元素内容高度的度量,包括由于溢出导致的视图中不可见内容. clientHeight:元素内部 ...