using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks; namespace ConsoleApplication6
{
public class PCQueue : IDisposable
{
class WorkItem
{
public readonly TaskCompletionSource<object> TaskSource;
public readonly Action Action;
public readonly CancellationToken? CancelToken; public WorkItem(
TaskCompletionSource<object> taskSource,
Action action,
CancellationToken? cancelToken)
{ TaskSource = taskSource;
Action = action;
CancelToken = cancelToken;
}
} BlockingCollection<WorkItem> _taskQ = new BlockingCollection<WorkItem>(); /// <summary>
/// 为每个消费者创建并启动单独的任务: 这里我启动了2个任务,用于打印easy和easy2这两个的顺序不一定
/// </summary>
/// <param name="workerCount"></param>
public PCQueue(int workerCount)
{
// 为每个消费者创建并启动单独的任务:
for (int i = ; i < workerCount; i++)
Task.Factory.StartNew(Consume);
} public void Dispose() { _taskQ.CompleteAdding(); } /// <summary>
/// 默认任务取消标识为null的任务进队方法
/// </summary>
/// <param name="action"></param>
/// <returns></returns>
public Task EnqueueTask(Action action)
{
return EnqueueTask(action, null);
}
/// <summary>
/// 任务进队方法含标识
/// </summary>
/// <param name="action"></param>
/// <param name="cancelToken"></param>
/// <returns></returns>
public Task EnqueueTask(Action action, CancellationToken? cancelToken)
{
var tcs = new TaskCompletionSource<object>();
_taskQ.Add(new WorkItem(tcs, action, cancelToken));
//通过TaskCompletionSource返回任务本身,可查看任务的响应信息如result,exception,status等等
return tcs.Task;
} void Consume()
{
foreach (WorkItem workItem in _taskQ.GetConsumingEnumerable())
if (workItem.CancelToken.HasValue &&
workItem.CancelToken.Value.IsCancellationRequested)
{
workItem.TaskSource.SetCanceled();
}
else
try
{
workItem.Action();
workItem.TaskSource.SetResult(); // 表示完成
}
catch (OperationCanceledException ex)
{
if (ex.CancellationToken == workItem.CancelToken)
workItem.TaskSource.SetCanceled();
else
workItem.TaskSource.SetException(ex);
}
catch (Exception ex)
{
workItem.TaskSource.SetException(ex);
}
}
}
class Program
{
static void Main(string[] args)
{
CancellationToken token1 = new CancellationToken(true);
//
var pcQ = new PCQueue();
Task task = pcQ.EnqueueTask(() => Console.WriteLine("Easy!"),token1);//输出easy的任务不会执行
task = pcQ.EnqueueTask(() => Console.WriteLine("Easy2!"));//会执行 // ...
Console.Read();
}
}
}

生产消费者队列(TaskCompletionSource)的应用的更多相关文章

  1. ZooKeeper实现生产-消费者队列

    [欢迎关注公众号:程序猿讲故事 (codestory),及时接收最新文章] 生产-消费者队列,用于多节点的分布式数据结构,生产和消费数据.生产者创建一个数据对象,并放到队列中:消费者从队列中取出一个数 ...

  2. BlockingQueue 阻塞队列(生产/消费者队列)

    1:BlockingQueue的继承关系 java.util.concurrent 包里的 BlockingQueue是一个接口, 继承Queue接口,Queue接口继承 Collection Blo ...

  3. Python进阶----进程之间通信(互斥锁,队列(参数:timeout和block),), ***生产消费者模型

    Python进阶----进程之间通信(互斥锁,队列(参数:timeout和block),), ***生产消费者模型 一丶互斥锁 含义: ​ ​ ​ 每个对象都对应于一个可称为" 互斥锁&qu ...

  4. Java多线程学习笔记--生产消费者模式

    实际开发中,我们经常会接触到生产消费者模型,如:Android的Looper相应handler处理UI操作,Socket通信的响应过程.数据缓冲区在文件读写应用等.强大的模型框架,鉴于本人水平有限目前 ...

  5. RabbitMQ下的生产消费者模式与订阅发布模式

    所谓模式,就是在某种场景下,一类问题及其解决方案的总结归纳.生产消费者模式与订阅发布模式是使用消息中间件时常用的两种模式,用于功能解耦和分布式系统间的消息通信,以下面两种场景为例: 数据接入   假设 ...

  6. Python——Queue模块以及生产消费者模型

    1.了解Queue Queue是python标准库中的线程安全的队列(FIFO)实现,提供了一个适用于多线程编程的先进先出的数据结构,即队列,用来在生产者和消费者线程之间的信息传递 |queue.Qu ...

  7. Kafka下的生产消费者模式与订阅发布模式

    原文:https://blog.csdn.net/zwgdft/article/details/54633105   在RabbitMQ下的生产消费者模式与订阅发布模式一文中,笔者以“数据接入”和“事 ...

  8. Linux——多线程下解决生产消费者模型

    我们学习了操作系统,想必对生产消费者问题都不陌生.作为同步互斥问题的一个经典案例,生产消费者模型其实是解决实际问题的基础模型,解决很多的实际问题都会依赖于它.而此模型要解决最大的问题便是同步与互斥.而 ...

  9. 生产消费者模式与python+redis实例运用(中级篇)

    上一篇文章介绍了生产消费者模式与python+redis实例运用(基础篇),但是依旧遗留了一个问题,就是如果消费者消费的速度跟不上生产者,依旧会浪费我们大量的时间去等待,这时候我们就可以考虑使用多进程 ...

随机推荐

  1. Inno Setup 软件封装

    例子: ; 脚本用 Inno Setup 脚本向导 生成. ; 查阅文档获取创建 INNO SETUP 脚本文件的详细资料! #define MyAppName "隧道照明系统客户端程序&q ...

  2. 《DSP using MATLAB》Problem 2.10

    代码: %% ------------------------------------------------------------------------ %% Output Info about ...

  3. 【Xamarin】Visual Studio 2013 Xamarin for iOS 环境搭建

    一.Mac安装Xamarin.iOS 1,我的Mac 环境:OSX 10.10.3.Xcode 6.3.2 (使用虚拟机亲测也成功  VMware 11 安装 Mac OS X10.10  ) Xam ...

  4. return 0;和exit(0);的区别

    首先说一下fork和vfork的差别: fork 是 创建一个子进程,并把父进程的内存数据copy到子进程中. vfork是 创建一个子进程,并和父进程的内存数据share一起用. 这两个的差别是,一 ...

  5. java自动装箱和自动拆箱

    启蒙:https://droidyue.com/blog/2015/04/07/autoboxing-and-autounboxing-in-java/ 1,比较:=比就和string一样比较地址,有 ...

  6. php 文件上传$_FILES中error返回值详解

    用PHP上传文件时,我们会用程序去监听浏览器发送过来的文件信息,首先会通 过$_FILES[fieldName]['error']的不同数值来判断此欲上传的文件状态是否正常.$_FILES[field ...

  7. Mysql的文件系统规划以及日志配置

    Mysql服务器文件系统规划: /dev/sda1 /boot /dev/sda2 / /dev/sda3 /home /dev/sda4 /tmp /dev/sdb1 /data /dev/sdc1 ...

  8. vs2010 光盘镜像免输入KEY 序列号

    用ULTRA ISO打开VS2010 ISO文件.找到\Setup\setup.sdb,提取出来编辑.用记事本打开.搜索到[Product Key]配置节,如果下面为空,补上KEY.如果是试用KEY, ...

  9. 汇编_指令_IRET

    IRET(interrupt return)中断返回,中断服务程序的最后一条指令.   汇编指令IRET [指令格式]IRET   [指令功能]IRET(interrupt return)中断返回,中 ...

  10. FancyButtons一个漂亮按钮的库

      一个功能强大且全面的按钮控件,是目前我见过的最好使的按钮. 支持给按钮添加图标,并且可通过属性设置手指按钮的效果,不需要在写<selector>文件. 项目地址:https://git ...