C#中神器类BlockingCollection的实现详解

作者:百宝门园地 时间:2022-10-13 07:41:02 

前言

如果你想玩转C# 里面多线程,工厂模式,生产者/消费者,队列等高级操作,就可以和我一起探索这个强大的线程安全提供阻塞和限制功能的C#神器类

BlockingCollection简单介绍

微软介绍地址:https://learn.microsoft.com/zh-cn/dotnet/standard/collections/thread-safe/blockingcollection-overviewBlockingCollection 是一个线程安全集合类,可提供以下功能:

  • 实现制造者-使用者模式

  • 通过多线程并发添加和获取项

  • 可选最大容量

  • 集合为空或已满时通过插入和移除操作进行阻塞

  • 插入和移除“尝试”操作不发生阻塞,或在指定时间段内发生阻塞

  • 封装实现 IProducerConsumerCollection 的任何集合类型

  • 使用取消标记执行取消操作

  • 支持使用 foreach(在 Visual Basic 中,使用 For Each)的两种枚举:1. 只读枚举,2. 在枚举项时将项移除的枚举

起手式

BlockingCollection blockingCollection = new(1);

new 操作符里面的数字是实现了可选最大容量,超出就线程阻塞了,程序一直卡在哪里

先来个开胃菜 => 三句代码实现线程阻塞

BlockingCollection<int> blockingCollection = new(1);
blockingCollection.Add(1);
blockingCollection.Add(2);

说明:因为限制队列只能插入一条,第一条没有消费掉,所以一直卡在插入第二条程序不会往下继续运行实现了集合为空或已满时通过插入和移除操作进行阻塞

正式开始前先分享一些多线程的知识点

Task类简单介绍

Task 表面上是Thread但却是对ThreadPool的封装,控制和扩展性很强,对线程的延续,阻塞,取消,超时,比传统的Thread和ThreadPool强

Queue类简单介绍

队列(Queue)代表了一个先进先出的对象集合。当您需要对各项进行先进先出的访问时,则使用队列。当您在列表中添加一项,称为入队,当您从列表中移除一项时,称为出队

接下来进入实际使用场景

场景一: 生产者=> 消费者

建议代码还是要动手实现一下,不然体会不到一边生产数据,同时还能取数据的神仙操作

int count = 0 ;
BlockingCollection<string> blockingCollection = new(1);
//生产者
Task.Factory.StartNew(() =>
{
while (true)
{
   blockingCollection.Add("String: " + count);
   count++;
   if (count > 10)
   {
    blockingCollection.CompleteAdding();
   }
}
});

//消费者
Task.Factory.StartNew(() =>
{
foreach (var element in blockingCollection.GetConsumingEnumerable())
{
 Thread.Sleep(1000);
 ("Work: " + element).Dump();//Dump 为工具Linq的功能
}
});

上面的代码中这个方法GetConsumingEnumerable很重要,它可以在BlockingCollection集合有数据的时候取数据,没有的话停止取,可以达到监测的效果

这个案例实现了如下功能:

  • 多线程并发添加和获取项

  • 生产者和消费者模式

  • 使用取消标记执行取消操作(让生产者知道我们已经不需要你工作了)

生产者/消费者输出结果

Work: String: 0
Work: String: 1
Work: String: 2
Work: String: 3
Work: String: 4
Work: String: 5
Work: String: 6
Work: String: 7
Work: String: 8
Work: String: 9
Work: String: 10

场景二: 实现队列FIFO(先进先出),LIFO(先进后出)

//先进先出(FIFO)
BlockingCollection<int> bc = new(new ConcurrentQueue<int>());
bc.Add(1);
bc.Add(2);
bc.CompleteAdding();

//先进后出(LIFO)
BlockingCollection<int> bc2 = new(new ConcurrentStack<int>());
bc2.Add(1);
bc2.Add(2);
bc2.CompleteAdding();

bc.Take().Dump("bc1:");
bc2.Take().Dump("bc2:");

队列输出结果

bc :1 
bc2: 2

这个简单的案例是想介绍一下其实:BlockingCollection也可以实现队列的功能

来源:https://www.cnblogs.com/baibaomen-org/p/17162795.html

标签:C#,BlockingCollection
0
投稿

猜你喜欢

  • elasticsearch数据信息索引操作action support示例分析

    2022-03-18 02:09:07
  • Java多线程Future松获取异步任务结果轻松实现

    2022-11-22 15:49:38
  • Android NDK开发(C语言字符串)

    2023-06-18 10:21:28
  • Hadoop之Mapreduce序列化

    2022-05-08 10:18:19
  • Java为什么基本数据类型不需要进行创建对象?

    2022-03-16 08:59:03
  • Android Compose Column列表不自动刷新问题

    2022-08-10 07:48:02
  • SpringBoot升级指定jackson版本的问题

    2022-05-31 13:18:49
  • Kotlin空安全空类型浅谈

    2022-06-18 22:48:49
  • 关于apollo和Spring集成@Value注解通用解析

    2022-03-30 23:06:03
  • C#常见的几种集合 ArrayList,Hashtable,List<T>,Dictionary<K,V> 遍历方法对比

    2021-07-25 17:00:04
  • 一文搞懂Java MD5算法的原理及实现

    2023-01-04 21:10:24
  • Java servlet后端开发超详细教程

    2022-11-01 06:13:50
  • SpringBoot中实现分布式的Session共享的详细教程

    2023-08-23 18:23:43
  • Android实现 EditText输入手机号空格功能

    2021-09-17 00:29:27
  • 如何在Mac下配置多个Java版本

    2023-11-07 05:14:34
  • Java后端Cookie实现(时间戳)代码实例

    2022-05-17 09:39:52
  • C#实现自定义Dictionary类实例

    2022-12-19 09:23:47
  • Java 获取Web项目相对webapp地址的实例

    2022-07-03 17:46:00
  • C#自定义类型强制转换实例分析

    2022-01-14 08:20:06
  • Spring Security基于JWT实现SSO单点登录详解

    2022-02-28 10:56:55
  • asp之家 软件编程 m.aspxhome.com