继上文<<基于阻塞队列的生产者消费者C#并发设计>>的并发队列版本的并发设计,原文code是基于<<.Net中的并行编程-4.实现高性能异步队列>>修改过来的,前面的几篇文章也详细介绍了并发实现的其它方案及实现。直接给code:

public class MyAsyncQueue<T>
{
//队列是否正在处理数据
private int isProcessing;
//有线程正在处理数据
private const int Processing = ;
//没有线程处理数据
private const int UnProcessing = ;
//队列是否可用 单线程下用while来判断,多线程下用if来判断,随后用while来循环队列的数量
private volatile bool enabled = true;
// 消费者线程
private Task currentTask;
// 消费者线程处理事件
public event Action<T> ProcessItemFunction;
//
public event EventHandler<EventArgs<Exception>> ProcessException;
// 并发队列
private ConcurrentQueue<T> queue;
// 消费者的数量
private int _internalTaskCount;
// 存储消费者队列
List<Task> tasks = new List<Task>(); public MyAsyncQueue()
{
_internalTaskCount = ;
queue = new ConcurrentQueue<T>();
Start();
} public int Count
{
get
{
return queue.Count;
}
}
// 开启监听线程
private void Start()
{
Thread process_Thread = new Thread(PorcessItem);
process_Thread.IsBackground = true;
process_Thread.Start();
} // 生产者生产
public void Enqueue(T items)
{
if (items == null)
{
throw new ArgumentException("items");
} queue.Enqueue(items);
DataAdded();
} //数据添加完成后通知消费者线程处理
private void DataAdded()
{
if (enabled)
{
if (!IsProcessingItem())
{
// 开启消费者消费队列
ProcessRangeItem();
}
}
} //判断是否队列有线程正在处理
private bool IsProcessingItem()
{
return !(Interlocked.CompareExchange(ref isProcessing, Processing, UnProcessing) == );
} private void ProcessRangeItem()
{
for(int i=; i< _internalTaskCount; i++)
{
currentTask = Task.Factory.StartNew(() => ProcessItemLoop());
tasks.Add(currentTask);
}
}
// 消费者处理事件
private void ProcessItemLoop()
{
Console.WriteLine("正在执行的Task的Id: {0}", Task.CurrentId);
// 队列为空,并且队列不可用
if (!enabled && queue.IsEmpty)
{
Interlocked.Exchange(ref isProcessing, );
return;
}
//处理的线程数 是否小于当前最大任务数
//if (Thread.VolatileRead(ref runingCore) <= this.MaxTaskCount)
//{
T publishFrame; while(enabled)
{
if (queue.TryDequeue(out publishFrame))
{
try
{
// 消费者处理事件
ProcessItemFunction(publishFrame);
}
catch (Exception ex)
{
OnProcessException(ex);
}
}
else
{
Console.WriteLine("线程Id{0}取队列失败,跳出循环", Task.CurrentId);
break;
}
}
} /// <summary>
///定时处理线程调用函数
///主要是监视入队的时候线程 没有来的及处理的情况
/// </summary>
private void PorcessItem(object state)
{
int sleepCount = ;
int sleepTime = ;
while (enabled)
{
//如果队列为空则根据循环的次数确定睡眠的时间
if (queue.IsEmpty)
{
// Task消费者消费完了队列中的数据....注销掉消费者线程
if(tasks.Count==_internalTaskCount)
{
Flush();
}
if (sleepCount == )
{
sleepTime = ;
}
else if (sleepCount <= )
{
sleepTime = * ;
}
else
{
sleepTime = * ;
}
sleepCount++;
Thread.Sleep(sleepTime);
}
else
{
//判断是否队列有线程正在处理
if (enabled && Interlocked.CompareExchange(ref isProcessing, Processing, UnProcessing) == )
{
if (!queue.IsEmpty)
{
currentTask = Task.Factory.StartNew(ProcessItemLoop);
tasks.Add(currentTask);
}
else
{
//队列为空,已经取完了
Interlocked.Exchange(ref isProcessing, );
}
sleepCount = ;
sleepTime = ;
}
}
}
} //更新并关闭消费者
public void Flush()
{
Stop();
foreach(var t in tasks)
{
if (t != null)
{
t.Wait();
Console.WriteLine("Task已经完成");
}
} // 消费者未消费完
while (!queue.IsEmpty)
{
try
{
T publishFrame;
if (queue.TryDequeue(out publishFrame))
{
ProcessItemFunction(publishFrame);
}
}
catch (Exception ex)
{
OnProcessException(ex);
}
}
currentTask = null;
tasks.Clear();
} public void Stop()
{
this.enabled = false;
} private void OnProcessException(System.Exception ex)
{
var tempException = ProcessException;
Interlocked.CompareExchange(ref ProcessException, null, null); if (tempException != null)
{
ProcessException(ex, new EventArgs<Exception>(ex));
}
}
}

调用code:

class ComInfo
{
public int ComId { get; set; } public DateTime Date { get; set; }
}
class Program
{
static MyAsyncQueue<ComInfo> queue = new MyAsyncQueue<ComInfo>();
static void Main(string[] args)
{
Console.WriteLine("开始======");
queue.ProcessItemFunction += A;
queue.ProcessException += C; //new EventHandler<EventArgs<Exception>>(C); ComInfo info = new ComInfo(); for (int i = ; i < ; i++)
{
Task.Factory.StartNew((param) =>
{
info = new ComInfo();
info.ComId = int.Parse(param.ToString());
info.Date = DateTime.Now.Date;
queue.Enqueue(info);
}, i);
} Console.WriteLine("结束======"); Console.ReadKey();
} static void A(ComInfo info)
{
Console.WriteLine(info.ComId + "====" + queue.Count);
} static void C(object ex, EventArgs<Exception> args)
{
Console.WriteLine("出错了");
}
}

并发系列应该就这样完了,回头整理成目录,自己查起来也方便

基于异步队列的生产者消费者C#并发设计的更多相关文章

  1. 基于阻塞队列的生产者消费者C#并发设计

    这是从上文的<<图文并茂的生产者消费者应用实例demo>>整理总结出来的,具体就不说了,直接给出代码,注释我已经加了,原来的code请看<<.Net中的并行编程-7 ...

  2. [并发编程 - socketserver模块实现并发、[进程查看父子进程pid、僵尸进程、孤儿进程、守护进程、互斥锁、队列、生产者消费者模型]

    [并发编程 - socketserver模块实现并发.[进程查看父子进程pid.僵尸进程.孤儿进程.守护进程.互斥锁.队列.生产者消费者模型] socketserver模块实现并发 基于tcp的套接字 ...

  3. Python之路(第三十八篇) 并发编程:进程同步锁/互斥锁、信号量、事件、队列、生产者消费者模型

    一.进程锁(同步锁/互斥锁) 进程之间数据不共享,但是共享同一套文件系统,所以访问同一个文件,或同一个打印终端,是没有问题的, 而共享带来的是竞争,竞争带来的结果就是错乱,如何控制,就是加锁处理. 例 ...

  4. Java并发(基础知识)—— 阻塞队列和生产者消费者模式

    1.阻塞队列                                                                                        Blocki ...

  5. Java并发编程()阻塞队列和生产者-消费者模式

    阻塞队列提供了可阻塞的put和take方法,以及支持定时的offer和poll方法.如果队列已经满了,那么put方法将阻塞直到有空间可用:如果队列为空,那么take方法将会阻塞直到有元素可用.队列可以 ...

  6. Java多线程—阻塞队列和生产者-消费者模式

    阻塞队列支持生产者-消费者这种设计模式.该模式将“找出需要完成的工作”与“执行工作”这两个过程分离开来,并把工作项放入一个“待完成“列表中以便在随后处理,而不是找出后立即处理.生产者-消费者模式能简化 ...

  7. 并发、并行、同步、异步、全局解释锁GIL、同步锁Lock、死锁、递归锁、同步对象/条件、信号量、队列、生产者消费者、多进程模块、进程的调用、Process类、

    并发:是指系统具有处理多个任务/动作的能力. 并行:是指系统具有同时处理多个任务/动作的能力. 并行是并发的子集. 同步:当进程执行到一个IO(等待外部数据)的时候. 异步:当进程执行到一个IO不等到 ...

  8. python并发编程-进程间通信-Queue队列使用-生产者消费者模型-线程理论-创建及对象属性方法-线程互斥锁-守护线程-02

    目录 进程补充 进程通信前言 Queue队列的基本使用 通过Queue队列实现进程间通信(IPC机制) 生产者消费者模型 以做包子买包子为例实现当包子卖完了停止消费行为 线程 什么是线程 为什么要有线 ...

  9. python进阶:Python进程、线程、队列、生产者/消费者模式、协程

    一.进程和线程的基本理解 1.进程 程序是由指令和数据组成的,编译为二进制格式后在硬盘存储,程序启动的过程是将二进制数据加载进内存,这个启动了的程序就称作进程(可简单理解为进行中的程序).例如打开一个 ...

随机推荐

  1. Retrofit 2.0 超能实践(三),轻松实现文件/多图片上传/Json字符串

    文:http://blog.csdn.net/sk719887916/article/details/51755427 Tamic 简书&csdn同步 通过前两篇姿势的入门 Retrofit ...

  2. 4.4、Android Studio在命令行运行Gradle

    默认情况下,在你的Gradle构建设置中有两种构建类型:一种是为了调试你的应用,debug类型:一种是构建最终的发布版本,release类型.无论你使用哪种模式,你的app必须在安装到设备或虚拟机中之 ...

  3. Xcode中为何要为设置bundle和App分别设置两份一样的图片资源

    大熊猫猪·侯佩原创或翻译作品.欢迎转载,转载请注明出处. 如果觉得写的不好请多提意见,如果觉得不错请多多支持点赞.谢谢! hopy ;) 我们知道在App设置的bundle中有时也会用到图片资源,而在 ...

  4. 百度的android面试总结分析

    今天就是今天上午10点,我接到了百度的电话面试,当然提前和我说了,我的拖延症是有多强烈,以至于我没怎么准备,当然我也想着看看自己的真实水平,在此检讨一下!!!!!!!!!!!!!!!!!!!!!!!! ...

  5. 任务定义器——SocketProcessor

    将socket扔进线程池前需要定义好任务,要进行哪些逻辑处理由SocketProcessor定义,根据线程池的约定,作为任务必须扩展Runnable.用如下伪代码表示 protected class ...

  6. 并发编程(二):分析Boost对 互斥量和条件变量的封装及实现生产者消费者问题

    请阅读上篇文章<并发编程实战: POSIX 使用互斥量和条件变量实现生产者/消费者问题>.当然不阅读亦不影响本篇文章的阅读. Boost的互斥量,条件变量做了很好的封装,因此比" ...

  7. 我眼中的Linux设备树(二 节点)

    二 节点(node)的表示首先说节点的表示方法,除了根节点只用一个斜杠"/"表示外,其他节点的表示形式如"node-name@unit-address".@前边 ...

  8. (五十一)KVC与KVO详解

    KVC的全称为key value coding,它是一种使用字符串间接更改对象属性的方法. 假设有一个Person类和一个Student类,其中Person类有age.name两个属性,Student ...

  9. 《java入门第一季》集合框架引入与面试题

    注:在开始的几篇集合介绍里,不包含泛型的概念.泛型在讲述所有集合后再加入进去. 集合的由来:    我们学习的是面向对象语言,而面向对象语言对事物的描述是通过对象体现的,为了方便对多个对象进行操作,我 ...

  10. 怎样将Android手机弄死机?

    将Android手机弄死机目前知道有两种方式: 第一种: 以root权限在shell中执行 stop 通过 start 但是这种串口还是可以用 第二种: suecho "c" &g ...