在C#中使用Channels的完整教程

前言

在面对 生产者-消费者 的场景下, netcore 提供了一个新的命名空间 System.Threading.Channels 来帮助我们更高效的处理此类问题,有了这个 Channels 存在, 生产者 和 消费者 可以各自处理自己的任务而不相互干扰,有利于两方的并发处理,这篇文章我们就来讨论下如何使用 System.Threading.Channels。

Dataflow vs Channel

在 System.Threading.Tasks.Dataflow 命名空间下提供了一个数据流库,主要封装了 存储 和 处理 两大块,该库专注于 pipeline 处理,而 System.Threading.Tasks.Channels 主要专注于 存储 这块,从单一职责上来说,在 生产者-消费者 场景下,Channels 比 Dataflow 性能要高得多。

为什么要使用 Channels

可以利用 Channels 来实现 生产者和消费者 之间的解耦,大体上有两个好处:

  • 生产者 和 消费者 是相互独立的,两者可以并行执行。
  • 如果生产者不给力,可以创建多个的生产者,如果消费者不给力,可以创建更多的消费者。

总的来说,在 生产者-消费者 模式下可以帮助我们提高应用程序的吞吐率。

安装 System.Threading.Channels

要想使用 Channel,需要用 nuget 引用 System.Threading.Channels 包,还可以通过 Visual Studio 2019 的 NuGet package manager 可视化界面安装 或者 通过 NuGet package manager 命令行工具输入以下命令:

dotnet add package System.Threading.Channels

创建 channel

本质上来说,你可以创建两种类型的 channel,一种是有限容量的 bound channel,一种是无限容量的 unbound channel,接下来的问题是,如何创建呢?Channels 提供了两种 工厂方法 用于创建,如下代码所示:

  • CreateBounded<T> 创建的 channel 是一个有消息上限的通道。
  • CreateUnbounded<T> 创建的 channel 是一个无消息上限的通道。

下面的代码片段展示了如何创建 unbounded channel,并且只能存放 string 类型。

 static void Main(string[] args)
 {
  var channel = Channel.CreateUnbounded<string>();
 }

对了,Bounded channel 还提供了一个 FullMode 属性,用于指定当 channel 已满时该如何对插入的 message 进行处理,通常有四种做法。

  • Wait
  • DropWrite
  • DropNewest
  • DropOldest

下面的代码片段展示了如何在 Bounded channel 上使用 FullMode。

 static void Main(string[] args)
 {
  var channel = Channel.CreateBounded<string>(new BoundedChannelOptions(1000)
  {
  FullMode = BoundedChannelFullMode.Wait
  });
 }

将消息写入到 channel

要想将 message 写入到 channel,可以使用 WriteAsync() 方法,如下代码所示:

  static async Task Main(string[] args)
  {
   var channel = Channel.CreateBounded<string>(new BoundedChannelOptions(1000)
   {
    FullMode = BoundedChannelFullMode.Wait
   });

   await channel.Writer.WriteAsync("Hello World!");
  }

从 channel 中读取消息

要想从 channel 中读取 message,可以使用 ReadAsync(),如下代码所示:

  static async Task Main(string[] args)
  {
   var channel = Channel.CreateBounded<string>(new BoundedChannelOptions(1000)
   {
    FullMode = BoundedChannelFullMode.Wait
   });

   while (await channel.Reader.WaitToReadAsync())
   {
    if (channel.Reader.TryRead(out var message))
    {
     Console.WriteLine(message);
    }
   }
  }

System.Threading.Channels 例子

下面是完整的代码清单,展示了如何从 channel 中读写 message。

 class Program
 {
  static async Task Main(string[] args)
  {
   await SingleProducerSingleConsumer();

   Console.ReadKey();
  }

  public static async Task SingleProducerSingleConsumer()
  {
   var channel = Channel.CreateUnbounded<int>();
   var reader = channel.Reader;
   for (int i = 0; i < 10; i++)
   {
    await channel.Writer.WriteAsync(i + 1);
   }

   while (await reader.WaitToReadAsync())
   {
    if (reader.TryRead(out var number))
    {
     Console.WriteLine(number);
    }
   }
  }
 }

可以看到,控制台中输出了数字 1-10,这些数字正是 Writer 写入到 channel 中的,对吧。

总的来说,要想使用 生产者-消费者 场景,有几种实现途径,比如:BlockingCollection 和 TPL Dataflow,但本篇介绍的 Channels 要比前面的两种性能更高,关于 Channels 更多的细节,我会在未来的文章中进行讨论,如果您现在想急于了解的话,可以参考MSDN: https://docs.microsoft.com/en-us/dotnet/api/system.threading.channels?view=netcore-3.0

总结

到此这篇关于在C#中使用Channels的文章就介绍到这了,更多相关C#使用Channels内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • 在C#中使用Channels的完整教程

    前言 在面对 生产者-消费者 的场景下, netcore 提供了一个新的命名空间 System.Threading.Channels 来帮助我们更高效的处理此类问题,有了这个 Channels 存在, 生产者 和 消费者 可以各自处理自己的任务而不相互干扰,有利于两方的并发处理,这篇文章我们就来讨论下如何使用 System.Threading.Channels. Dataflow vs Channel 在 System.Threading.Tasks.Dataflow 命名空间下提供了一个数据流

  • Java8中的lambda表达式入门教程

    1.基本介绍 lambda表达式,即带有参数的表达式,为了更清晰地理解lambda表达式,先上代码: 1.1 两种方式的对比 1.1.1 方式1-匿名内部类 class Student{ private String name; private Double score; public Student(String name, Double score) { this.name = name; this.score = score; } public String getName() { ret

  • 利用RJB在Ruby on Rails中使用Java代码的教程

    开始之前 关于本教程 Ruby on Rails (Rails) 是用 Ruby 编写的一个 full-stack Web 应用程序框架,而 Ruby 是一种功能丰富的.免费的.可扩展的.可移植的.面向对象的脚本编制语言.Rails 在 Web 应用程序开发人员之间非常流行.通过它,可以快速有效地开发 Web 应用程序,并将其部署到任何 Web 容器中,例如 IBM? WebSphere? 或 Apache Tomcat. 在 Rails 和类似的 Web 应用程序开发框架出现之前,用于 Web

  • python操作oracle的完整教程分享

    1. 连接对象 操作数据库之前,首先要建立数据库连接. 有下面几个方法进行连接. >>>import cx_Oracle >>>db = cx_Oracle.connect('hr', 'hrpwd', 'localhost:1521/XE') >>>db1 = cx_Oracle.connect('hr/hrpwd@localhost:1521/XE') >>>dsn_tns = cx_Oracle.makedsn('localho

  • IntelliJ IDEA 中git的使用图文教程

    项目管理离不开版本控制,目前主流版本控制工具大概就是SVN和Git,至于两者有啥区别这里就不详细介绍了,如果有不明白的可以上网查资料,后期如果有机会我再开篇栏目细说,而且现在市场上Git的使用率已经远远高于SVN.我们在用IDEA开发项目的时候如何熟练使用Git来控制代码版本呢? 一.安装Git 使用Git当然需要先安装Git,安装过程就不详细说明了,按装好之后,打开IDEA进入设置界面(可以直接点击工具栏上的,也可以通过快捷键Ctrl + Alt + S),搜索git,界面如下: 我们可以看到

  • java 中maven pom.xml文件教程详解

    maven pom.xml文件教程详解,具体内容如下所示: <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.x

  • Linux服务器部署JavaWeb项目完整教程

    本文大部分参考网上其他教程,是实际操作后回过头来的一些总结,希望可以对正在部署项目的你有所帮助. 基本环境:Centos7.tomcat8.jdk8,MySQL5.6.nginx 安装JDK yum install java-1.8.0-openjdk* -y 使用yum安装,无需配置系统环境,执行完这条命令后JDK就安装好了. 安装Mysql 我们这里使用Mysql,如果使用MariaDB ,一般云服务器有安装,只需要升级就可以. 安装步骤: # wget http://dev.mysql.c

  • Ubuntu 18.04上安装Apache、MySQL、PHP、LAMP的完整教程

    1.安装 Apache $ sudo apt update && sudo apt install apache2 中间会遇到停顿询问是否继续, 输入 y 然后 回车. 2.测试 Apache 通过查看 Apache 服务的状态,检查 Apache 是否安装正确. $ sudo service apache2 status 查看完状态, 你需要按下 q 退出, Apache server的状态. 查看之后,知道Apache的服务已经起来了,那么下一步应该去查看一些Apache web页面.

  • 使用keras实现孪生网络中的权值共享教程

    首先声明,这里的权值共享指的不是CNN原理中的共享权值,而是如何在构建类似于Siamese Network这样的多分支网络,且分支结构相同时,如何使用keras使分支的权重共享. Functional API 为达到上述的目的,建议使用keras中的Functional API,当然Sequential 类型的模型也可以使用,本篇博客将主要以Functional API为例讲述. keras的多分支权值共享功能实现,官方文档介绍 上面是官方的链接,本篇博客也是基于上述官方文档,实现的此功能.(插

  • Git Submodule使用完整教程(小结)

    自从看了蒋鑫的<Git权威指南>之后就开始使用Git Submodule功能,团队也都熟悉了怎么使用,多个子系统(模块)都能及时更新到最新的公共资源,把使用的过程以及经验和容易遇到的问题分享给大家. Git Submodule功能刚刚开始学习可能觉得有点怪异,所以本教程把每一步的操作的命令和结果都用代码的形式展现给大家,以便更好的理解. 1.对于公共资源各种程序员的处理方式 每个公司的系统都会有一套统一的系统风格,或者针对某一个大客户的多个系统风格保持统一,而且如果风格改动后要同步到多个系统中

随机推荐