今天给大家分享一个微软官方的好东西:Channel。

前言

今天给大家分享一个微软官方的生产者/消费者方案的特性解决:Channel。

Channel在System.Threading.Channels命名空间下,Core 2.1使用时,需要从Nuget上安装。

% dotnet add package System.Threading.Channels

而在Core 3.0 preview 7开始,就直接包含在框架中了。

这是一个相对较新的特性。从Core 2.1开始加入,现在版本是5.0.0(嗯,这个版本号有点骗人,Channel的第一个版本就是4.5.0)。

Channel能做什么?

逻辑上,Channel实际就是一个高效的、线程安全的队列,支持在生产者和消费者之间传递数据。

利用Channel,通过发布和订阅,可以将生产者和消费者分开。生产者Producer负责接收请求,并写入Channel,而消费者Consumer为每个进入Channel的数据执行处理。这样做,一方面可以使生产者和消费者并行工作来提高性能,另一方面,可以通过创建更多的生产者或消费者来提高应用的吞吐量。

下面,我们以一个实际例子,来解释这个特性。

创建Channel

Channel提供了一个静态Channel类,提供了两个公开方法来创建两种类型的Channel。

  • CreateUnbounded - 创建一个具有无限容量的Channel。

  • CreateBounded - 创建一个具有有限容量的Channel。

人通常来说,这两种方式使用上没有太大的区别。实际应用中,具体要看生产和消费的速度,以及期望产生的结果。有限容量的Channel,容量是有上限的,到达上限后,可以让生产者非阻塞等待消费者使用并释放Channel容量后再继续。这种方式,好处是可以控制生产的速度,控制系统资源的使用,缺点也是。因为控制速度意味着生产速度会被限制,甚至停止。而无限容量,生产者可以全速进行生产。但也有缺点,如果消费者的消费速度低于生产者,Channel的资源使用会无限增加,会有服务器资源耗尽的可能。

今天的例子,我们使用无限Channel。

var channel = Channel.CreateUnbounded<string>();

非常简单的一行代码,就创建了一个无限容量的Channel。

我们定义这个Channel用来保存字符串对象。

创建方法是一个通用的工厂方法,所以我们可以为需要使用的任何类型的对象和数据创建Channel。

Channel有两个属性:阅读器返回ChannelReader,写入器返回ChannelWriter。

写入Channel

使用写入器ChannelWriter,可以对Channel进行写入操作。ChannelWriter提供了以下几个方法:

  • WriteAsync - 异步写入

  • WaitToWriteAsync - 非阻塞等待,直到有空间可写入时或Channel关闭时,返回true/false

  • TryWrite - 尝试写入

  • Complete - 标记Channel为关闭,并不再写入数据到该Channel

  • TryComplete - 尝试标记Channel为关闭。

这几个方法很容易理解,就不解释了。

在本文的例子里,我用了:

await channel.Writer.WriteAsync("New message");

读取Channel

使用阅读器ChannelReader从Channel进行数据的读取。也提供了几个方法:

  • ReadAsync - 异步读取

  • ReadAllAsync - 异步读取Channel中的所有数据

  • TryRead - 尝试读取

  • WaitToReadAsync - 非阻塞等待,直到有数据可读取或Channel关闭时,返回true/false

不同的消费者模式,会用到不同的读取方法。这个根据经验来写就好。

本文的例子中,我是采用WaitToReadAsync和ReadAsync配合来使用的:

while (await ChannelReader.WaitToReadAsync())
{if (ChannelReader.TryRead(out var timeString)){/***/}
}

WaitToReadAsync是一个非阻塞等待,在有消息可读或Channel关闭时,才会唤醒并继续。

考虑到有多个消费者的情况,有可能别的线程已经进行了读取,这儿使用TryRead进行读取操作。

要注意:数据的同步工作是由Channel进行管理的。Channel会确保多个消费者不会读到相同的数据。Channel同时也管理数据的次序。

示例代码

今天的示例代码我放到了Github上。链接是文章最后。

这个例子中,我做了三个场景。

首先是Channel。我使用了无限Channel。然后是创建生产者和消费者。数据传输过程就简单化了,生产者只简单将一个字符串写入到Channel。消费者也是,简单等待并从Channel读取数据字符串,写入控制台。

三个场景分别是:

单一生产者/单一消费者

这个例子中,创建了一个生产者和一个消费者。两者的任务都是并发启动的。

里面的延时,是用来模拟工作负载的。

多个生产者/单一消费者

这个例子中有两个生产者。通常在应用中有多个生产者时,我们需要确保生产与单个消费者所能处理的消息数量大致相当,这样能更好地利用服务器资源。

单一生产者/多个消费者

这个其实是应用中最常见的情况,就是产生消息很快,但处理工作相关较慢,而且工作也更密集。这种情况,实际应用中我们可以通过扩大消费者数量来满足生产的需求。

总结

最近的项目在做一个大数据的采集,用到了一些Channel的技术。然后发现网上这部分内容很少,就做了个例子,写了这个文章。

Channel内容本身并不多,但用着很方便,而且实际应用中,比想像的更强大。它可以简化很多生产者/消费者模式的使用,而且,任务间交换数据,使用Channel会更方便,更直接。

示例代码在:https://github.com/humornif/Demo-Code/tree/master/0033/demo

喜欢就来个三连,让更多人因你而受益

Dotnet Core下的Channel, 你用了吗?相关推荐

  1. entity framework core mysql,DotNet Core下使用 EntityFrameworkCore 操作MySQL (一)

    1.新建一个Core的Web项目 注意:选择的是2.0版本 添加依赖项 依赖项>右键>管理NuGet程序包 输入以下包名 MySql.Data.EntityFrameworkCore 然后 ...

  2. dotnet core高吞吐Http api服务组件FastHttpApi

    简介 是dotNet core下基于Beetlex实现的一个高度精简化和高吞吐的HTTP API服务开源组件,它并没有完全实现HTTP SERVER的所有功能,而是只实现了在APP和WEB中提供数据服 ...

  3. dotnet core Linux下图片验证码解决方案

    dotnet core Linux下图片验证码解决方案 参考文章: (1)dotnet core Linux下图片验证码解决方案 (2)https://www.cnblogs.com/xxff/p/9 ...

  4. dotNET Core实现分布式环境下的流水号唯一

    业务背景 在管理系统中,很多功能模块都会涉及到各种类型的编号,例如:流程编号.订单号.合同编号等等.编号各有各自的规则,但通常有一个流水号来确定编号的唯一性,保证流水号的唯一,在不同的环境中实现方式有 ...

  5. 边缘化搭建 DotNet Core 2.1 自动化发布和部署(下)

    写在前面 本篇文章是上一篇边缘化搭建 DotNet Core 2.1 自动化发布和部署(上)的后续操作,本文主要讲解如何开启Docker Remote API,开启Remote API后的权限安全问题 ...

  6. 【Step By Step】将Dotnet Core部署到Docker下

    一.使用.Net Core构建WebAPI并访问Docker中的Mysql数据库 这个的过程大概与我之前的文章<尝试.Net Core-使用.Net Core + Entity FrameWor ...

  7. windows使用.NET CORE下创建MVC,发布到linux运行

    1.在有dotnet core 的环境下,打开控制台.创建文件夹demo1 2.创建MVC程序 3.创建完成 4.使用记事本修改一下HomeController 修改端口 5.发布 6.压缩发布的文件 ...

  8. centos 6.5 安装dotnet core 2.2

    .net core 官网地址 https://dotnet.microsoft.com/download 本次安装版本为.net core SDK v2.2.101 1.查看系统版本, 升级系统基本l ...

  9. k8s pod部署到不同node_部署Dotnet Core应用到Kubernetes(一) - 老王Plus

    最近闲了点,写个大活:部署Dotnet应用到K8s. 写在前边的话 一直想完成这个主题.但这个主题实在太大了,各种拖延症的小宇宙不时爆发一下,结果就拖到了现在. 这个主题,会是一个系列.在这个系列中, ...

最新文章

  1. python动态图-Python图像处理之gif动态图的解析与合成操作详解
  2. 实战项目四:爬取911网站
  3. python集合例题_python练习题集合-2
  4. 解决magento保存产品时耗时很长的问题
  5. 一、从零创建VUE项目
  6. 158 行 Python 代码,复现 DeepMind 递归神经网络 DRAW!
  7. Ruby IDE及相关书籍
  8. boost::bind 与 boost::function 的使用方法例子
  9. java异常处理拦截器
  10. javascript 使用zlib发送wss请求,接收blob,并解压
  11. centos 计算器_Linux下的计算器
  12. 我的世界java版如何加披风_我的世界披风怎么导入
  13. 利用jsPDF把图片转成pdf格式保存本地指定目录
  14. ffmpeg转码过程分析
  15. 专业计算机术语中英文对照(一)
  16. 淘宝视频的跨模态检索
  17. Linux下7za对rar文件解压失败问题
  18. 【Pandas】多种添加行列数据方法
  19. 《小学四则运算练习软件软件需求说明》结对项目报告
  20. 人工智能机器人制造的研发之路

热门文章

  1. leetcode13
  2. CF449 C. Jzzhu and Apples
  3. c#调用存储过程查询表并返回影响的行数
  4. Ubuntu16.04换源
  5. 游戏开发Camera之Cinematic Camera-深度
  6. WPF企业内训全程实录(下)
  7. 百度家电行业报告摘录
  8. vnc数量限制_通过限制视觉效果在Vista上加速VNC
  9. 上周面试回来后写的Java面试总结,想进BAT必看
  10. CSS属性总结之background