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


猜你喜欢
- 前言:在android HTML5 开发中有不少人遇到过 audio 标签 autoplay在某些设备上无效的问题,网上大多是讲怎么在js中
- 本文实例为大家分享了java后台批量下载文件并压缩成zip下载的具体代码,供大家参考,具体内容如下因项目需要,将服务器上的图片文件压缩打包z
- 编写一个 Java 应用程序,实现图形界面多人聊天室(多线程实现),要求聊天室窗口标题是 “欢迎使用 XXX 聊天室应用
- 本文实例为大家分享了Android实现画画板的具体代码,供大家参考,具体内容如下① 准备一个布局文件<?xml version=&qu
- 一、添加联系人Intent addIntent = new Intent(Intent.ACTION_INSERT,Uri.withAppe
- 不得不说opencv是个强大的东东,以前做一个项目的一个模块时使用到进行图形处理,这次是想将一个视频的播放放慢,以前在网上看到opencv有
- 1、SQLite介绍SQLite,是一款轻型的数据库,是遵守的ACID关系型数据库管理系统,它包含在一个相对小的C库中。它的设计目标嵌入式是
- android的WebView组件可以说是相当的强大,现将项目中经常用到的几个功能总结如下:一、背景设置WebView.setBackgro
- 第一次下载好Android源代码工程后,我们通常是在Android源代码工程目
- // 声明LocationManager对象 LocationManager loctionManager; // 通过系统服务,取得Loc
- 一.组合widget实现1.android和flutter自定义控件对比Android中,一般会继承View或已经存在的某个控件,然后覆盖d
- 之前讲到了自定义Adapter传递给ListView时,因为ListView的View回收,需要注意当ListView列表项中包含有带有状态
- 为了让我提供的通用 Mapper 的 boot-starter 同时兼容 Spring Boot 1.x 和 2.x,增加了这么一个工具类。
- 本文为大家分享了如何使用eclipse创建java项目,供大家参考,具体内容如下首先,打开Eclipse,在工具栏依次点击【File】>
- 本文实例讲述了C#实现更改MDI窗体背景颜色的方法。分享给大家供大家参考。具体实现方法如下:/// <summary>/// 设
- 本文实例讲述了C#实现客户端弹出消息框封装类。分享给大家供大家参考。具体如下:asp.net在服务器端运行,是不能在服务器端弹出对话框的,但
- 每次写批量的时候,都要在网上搜索一下,虽然都做过多次了,但具体的自己还是记不住(汗颜),所以索性今天就记录下来。前期说明:foreach的主
- 用来记录自己所用到的知识前两天在做项目的时候发现有时候在访问网络数据的时候由于后台要做的工作较多,给我们返回数据的时间较长,所以老大叫我加了
- 之前使用OnSharedPreferenceChangeListener,遇到了点小问题,就是有些时候OnSharedPreferenceC
- 从一开始写Android程序,就被告知这些常识1.长度宽度的数值要使用dp作为单位放入dimens.xml文件中2.字体大小的数值要使用sp