Channel 是干什么的

The System.Threading.Channels namespace provides a set of synchronization data structures for passing data between producers and consumers asynchronously. The library targets .NET Standard and works on all .NET implementations.

Channels are an implementation of the producer/consumer conceptual programming model.

以上是微软官方的解释 channels。用中文说的话就是这个类提供了在生产者跟消费者之间异步传统数据的能力,简单来说可以认为是一个内存消息队列。

示例 1

下面是一个简单的示例,说明如何使用 Channel 类来创建一个生产者-消费者模型:

    static async Task Main(string[] args)
{
var channel = Channel.CreateUnbounded<int>(); var producer = Task.Run(async () =>
{
for (int i = 0; i < 10; i++)
{
await channel.Writer.WriteAsync(i);
await Task.Delay(1000); // 模拟生产者需要一些时间来生成数据
} channel.Writer.Complete();
}); var consumer = Task.Run(async () =>
{
await foreach (var item in channel.Reader.ReadAllAsync())
{
Console.WriteLine($"消费者接收到: {item}");
}
}); await Task.WhenAll(producer, consumer);
}

在这个例子中,我们创建了一个无界的通道,然后创建了两个任务,一个是生产者,一个是消费者。生产者每秒生成一个数字,然后写入通道。消费者从通道中读取数据并打印出来。当生产者完成写入后,它会调用 channel.Writer.Complete() 来通知消费者没有更多的数据可以读取。

示例 2

你可以使用 Channel.CreateBounded(capacity) 方法来创建一个有界的通道,其中 capacity 参数指定了通道的容量。当通道满时,尝试写入的操作将会阻塞,直到有空间可用。

    static async Task Main(string[] args)
{
var channel = Channel.CreateBounded<int>(5); // 创建一个容量为5的有界通道 var producer = Task.Run(async () =>
{
for (int i = 0; i < 10; i++)
{
await channel.Writer.WriteAsync(i);
Console.WriteLine($"生产者生成了: {i}");
await Task.Delay(1000); // 模拟生产者需要一些时间来生成数据
} channel.Writer.Complete();
}); var consumer = Task.Run(async () =>
{
await foreach (var item in channel.Reader.ReadAllAsync())
{
Console.WriteLine($"消费者接收到: {item}");
await Task.Delay(2000); // 模拟消费者需要一些时间来处理数据
}
}); await Task.WhenAll(producer, consumer);
}

在这个例子中,我们创建了一个容量为5的有界通道。生产者每秒生成一个数字,然后写入通道。消费者从通道中读取数据并打印出来,但消费者处理数据的速度比生产者慢,所以当通道满时,生产者的 WriteAsync 操作将会阻塞,直到消费者读取了一些数据,使得通道有空间可用。

示例 3

下面是一个示例,展示了如何在多个生产者和消费者之间共享一个通道:

    static async Task Main(string[] args)
{
var channel = Channel.CreateUnbounded<int>(); // 创建两个生产者
var producer1 = Produce(channel.Writer, id: 1);
var producer2 = Produce(channel.Writer, id: 2); // 创建两个消费者
var consumer1 = Consume(channel.Reader, id: 1);
var consumer2 = Consume(channel.Reader, id: 2); // 等待所有生产者和消费者完成
await Task.WhenAll(producer1, producer2, consumer1, consumer2);
} static async Task Produce(ChannelWriter<int> writer, int id)
{
for (int i = 0; i < 10; i++)
{
await writer.WriteAsync(i);
Console.WriteLine($"生产者{id}生成了: {i}");
await Task.Delay(1000); // 模拟生产者需要一些时间来生成数据
} writer.Complete();
} static async Task Consume(ChannelReader<int> reader, int id)
{
await foreach (var item in reader.ReadAllAsync())
{
Console.WriteLine($"消费者{id}接收到: {item}");
await Task.Delay(2000); // 模拟消费者需要一些时间来处理数据
}
}

在这个例子中,我们创建了两个生产者和两个消费者,它们都共享同一个通道。这是一个非常重要使用模式。因为当我们使用消息队列的时候往往会有多个生产者跟多个消费者。我们可以通过控制生产者生产的速度来控制推入队列的数据量。我们还可以通过控制消费者的数量来控制消费数据的速度,从而来调节系统的流量,达到消峰填谷的作用。

总结

Channel 类是 .NET CORE 3.0 后新加入的类。为我们提供了便利的生产者/消费者模式实现方案。相当于是一个进程内的内存队列,而且它没有持久化,纯内存操作,性能是非常非常高的。当我们面对真正的高并发的时候可以为我们的系统提供吞吐量。当然代价是内存跟放弃一些实时性。

关注我的公众号一起玩转技术

.NET 中 Channel 类简单使用的更多相关文章

  1. python中的类简单讲解

    类似其它的语言, Python 中的函数使用小括号( () )调用.函数在调用之前必须先定义.如果函数中没有 return 语句, 就会自动返回 None 对象.      Python 是通过引用调 ...

  2. java中Color类的简单总结

    java中Color类的简单总结 1.颜色的常识 任何颜色都是由三原色组成(RGB),JAVA中支持224为彩色,即红绿蓝分量取值 介于0-255之间(8位表示) 2.Color类中的常量 publi ...

  3. 小师妹学JavaIO之:NIO中Channel的妙用

    目录 简介 Channel的分类 FileChannel Selector和Channel DatagramChannel SocketChannel ServerSocketChannel Asyn ...

  4. Processing中PImage类和loadImage()、createImage()函数的相关解析

    聊一聊Processing中PImage类和loadImage().createImage()函数.因为要借P5做多媒体创意展示,图片是一个很重要的媒体.有必要就图片的获取和展放作总结. 首先 有一点 ...

  5. Objective-C中的类目,延展,协议

    Objective-C中的类目(Category),延展(Extension),协议(Protocol)这些名词看起来挺牛的,瞬间感觉OC好高大上.在其他OOP语言中就没见过这些名词,刚看到这三个名词 ...

  6. CSS中伪类及伪元素用法详解

    CSS中伪类及伪元素用法详解   伪类的分类及作用: 注:该表引自W3School教程 伪元素的分类及作用: 接下来让博主通过一些生动的实例(之前的作业或小作品)来说明几种常用伪类的用法和效果,其他的 ...

  7. JAVA中的类和接口

    1.类: 类是具有相同属性和方法的一组对象的集合,它为属于该类的所有对象提供了统一的抽象描述,其内部包括属性和方法两个主要部分.在面向对象的编程语言中,类是一个独立的程序单位,它应该有一个类名并包括属 ...

  8. 《CoffeeScript应用开发》学习:第五章 CoffeeScript中的类

    在CoffeeScript中定义类 在CoffeeScript中,使用class定义类,使用关键字new实例化对象. 给类绑定方法 class Airplane takeOff: -> cons ...

  9. Delphi中线程类TThread实现多线程编程1---构造、析构……

    参考:http://www.cnblogs.com/rogee/archive/2010/09/20/1832053.html Delphi中有一个线程类TThread是用来实现多线程编程的,这个绝大 ...

  10. C++中派生类对象的内存布局

    主要从三个方面来讲: 1 单一继承 2 多重继承 3 虚拟继承 1 单一继承 (1)派生类完全拥有基类的内存布局,并保证其完整性. 派生类可以看作是完整的基类的Object再加上派生类自己的Objec ...

随机推荐

  1. Python生成唯一ID----UUID

    # UUID 生成唯一ID # uuid 是Python内置模块,主要有五种算法. import uuid # uuid1() 基于时间戳 a1 = uuid.uuid1() print('uuid1 ...

  2. Unable to determine application id: com.android.tools.idea.run.ApkProvisionException: No outputs for the main artifact of variant: debug

    前言 遇到这种情况极大可能属于gradle 与 android studio版本不匹配的情况. 因为我是在升级android studio遇到的这个问题. 方法 一个方法是:降低android stu ...

  3. em/px/rem/vh/vw的区别

    一.介绍 传统的项目开发中,我们只会用到px.%.em这几个单位,它可以适用于大部分的项目开发,且拥有比较良好的兼容性 从CSS3开始,浏览器对计量单位的支持又提升到了另外一个境界,新增了rem.vh ...

  4. json文件读取并转换成为字典python

    # JSON到字典转化 f2 = open('info.json', 'r') info_data = json.load(f2) print(info_data) # 显示数据类型 print(ty ...

  5. Python环境和PyCharm搭建教程

    1.python下载和安装 1.访问Python 官网:https://www.python.org/ 2.以Windows为例,我们选择一个稳定的版本进行安装,这里需要注意选择和自己操作系统类型一致 ...

  6. Oracle 查询超级慢之buffer sort

    查询超级慢之buffer sort 在视图中增加了一个临时表作为一个数据源进行id和名称的转换,没加的时候一秒不到,加了以后14秒,感觉有点问题,于是打开了解释计划看了下,发现这个buffer sor ...

  7. 力扣205(java)-同构字符串(简单)

    题目: 给定两个字符串 s 和 t ,判断它们是否是同构的. 如果 s 中的字符可以按某种映射关系替换得到 t ,那么这两个字符串是同构的. 每个出现的字符都应当映射到另一个字符,同时不改变字符的顺序 ...

  8. 力扣357(java)-统计各位数字都不同的数字个数(中等)

    题目: 给你一个整数 n ,统计并返回各位数字都不同的数字 x 的个数,其中 0 <= x < 10n . 示例 1: 输入:n = 2输出:91解释:答案应为除去 11.22.33.44 ...

  9. 记一次 JMeter 压测 HTTPS 性能问题

    ​简介:在使用 JMeter 压测时,发现同一后端服务,在单机 500 并发下,HTTP 和 HTTPS 协议压测 RT 差距非常大.同时观测后端服务各监控指标水位都很低,因此怀疑性能瓶颈在 JMet ...

  10. MySQL 深潜 - MDL 锁的实现与获取机制

    简介:本文将介绍在 MDL 系统中常用的数据结构及含义,然后从实现角度讨论 MDL 的获取机制与死锁检测,最后分享在实践中如何监控 MDL 状态. ​ 作者 | 泊歌 来源 | 阿里技术公众号 一 背 ...