队列(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多线程编程的更多相关文章

  1. 5天玩转C#并行和多线程编程 —— 第四天 Task进阶

    5天玩转C#并行和多线程编程系列文章目录 5天玩转C#并行和多线程编程 —— 第一天 认识Parallel 5天玩转C#并行和多线程编程 —— 第二天 并行集合和PLinq 5天玩转C#并行和多线程编 ...

  2. 5天玩转C#并行和多线程编程 —— 第三天 认识和使用Task

    5天玩转C#并行和多线程编程系列文章目录 5天玩转C#并行和多线程编程 —— 第一天 认识Parallel 5天玩转C#并行和多线程编程 —— 第二天 并行集合和PLinq 5天玩转C#并行和多线程编 ...

  3. Scalaz(45)- concurrency :Task-函数式多线程编程核心配件

    我们在上一节讨论了scalaz Future,我们说它是一个不完善的类型,最起码没有完整的异常处理机制,只能用在构建类库之类的内部环境.如果scalaz在Future类定义中增加异常处理工具的话,用户 ...

  4. 新手浅谈Task异步编程和Thread多线程编程

    初学Task的时候上网搜索,看到很多文章的标题都是task取代thread等等相关,我也一直以为task和thread是一类,其实task是.net4.0提出的异步编程,在之前.net1.0有dele ...

  5. C#多线程编程(1)--线程,线程池和Task

    新开了一个多线程编程系列,该系列主要讲解C#中的多线程编程.    利用多线程的目的有2个: 一是防止UI线程被耗时的程序占用,导致界面卡顿:二是能够利用多核CPU的资源,提高运行效率. 我没有进行很 ...

  6. 转载 .Net多线程编程—任务Task https://www.cnblogs.com/hdwgxz/p/6258014.html

    .Net多线程编程—任务Task   1 System.Threading.Tasks.Task简介 一个Task表示一个异步操作,Task的创建和执行是独立的. 只读属性: 返回值 名称 说明 ob ...

  7. .NET 4中的多线程编程之一:使用Task(转载)

    原文地址:http://www.cnblogs.com/yinzixin/archive/2011/11/04/2235233.html .NET 4为了简化多线程编程,提供了System.Threa ...

  8. 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 ...

  9. 5天玩转C#并行和多线程编程 —— 第二天 并行集合和PLinq

    5天玩转C#并行和多线程编程系列文章目录 5天玩转C#并行和多线程编程 —— 第一天 认识Parallel 5天玩转C#并行和多线程编程 —— 第二天 并行集合和PLinq 5天玩转C#并行和多线程编 ...

随机推荐

  1. HPU积分赛 2019.8.18

    A题 给出n个数,问这n个数能不能分成奇数个连续的长度为奇数并且首尾均为奇数的序列 Codeforces849A 题解传送门 代码 1 #include <bits/stdc++.h> 2 ...

  2. Oracle之增、删、改、查

    结构化查询语言 (Structured Query Language, SQL) SQL的组成: 数据操作语言(DML) 对数据进行查询.插入.删除和修改等操作,例如SELECT.INSERT.UPD ...

  3. Drools的Eclipse_IDEA插件安装

    1.说明 Drools使用时不是必须依赖插件的, 只是在安装了相应的插件之后, 在开发工具中能识别到对应的drools文件, 能够进行一些智能提示. 以及使用插件提供的便捷功能. 2.Eclipse插 ...

  4. Git 远程分支常用操作

    # 查看远程仓库推拉地址,分支信息,分支跟踪情况等 git remote show origin # 拉取远程仓库的变更内容到本地 git fetch origin # 拉取并合并仓库的变更内容到本地 ...

  5. Flask_请求钩子(七)

    在客户端和服务器交互的过程中,有些准备工作或扫尾工作需要处理,比如: 在请求开始时,建立数据库连接: 在请求开始时,根据需求进行权限校验: 在请求结束时,指定数据的交互格式: 为了让每个视图函数避免编 ...

  6. post请求后获取不到请求头信息的原因

    在前台获取数据时,因为没有条件,所以不用传数据,用的post请求.再添加token验证时想着前端在请求时直接添加一个请求头信息就ok 没想到后台却获取不到请求头信息,打印了下日志发现是null,这是怎 ...

  7. MYSQL实现上一条下一条功能

    select id from(select *, (@i:=@i+1) as rownum from pre_bet_zhibo,(select @i:=0) as itwhere link_cone ...

  8. 10个JS技巧

    1.过滤唯一值 Set 对象是es6新引入的,配合扩展运算符[...]一起使用,我们可以用它来过滤数组的唯一值. const array = [1, 1, 2, 3, 5, 5, 1] const u ...

  9. test_1 计算字符串最后一个单词的长度,单词以空格隔开

    题目描述:计算字符串最后一个单词的长度,单词以空格隔开.  输入描述: 一行字符串,非空,长度小于5000. 输出描述: 整数N,最后一个单词的长度. #coding=utf-8 str = raw_ ...

  10. 原生twig模板引擎详解(安装使用)

    最近在学习SSTI(服务器模板注入),所以在此总结一下 0x00 Twig的介绍 什么是Twig? Twig是一款灵活.快速.安全的PHP模板引擎. Twig的特点? 快速:Twig将模板编译为纯粹的 ...