当前位置: 首页 > news >正文

理解并掌握C#的Channel:从使用案例到源码解读(一)

引言

在C#的并发编程中,Channel是一种非常强大的数据结构,用于在生产者和消费者之间进行通信。本文将首先通过一个实际的使用案例,介绍如何在C#中使用Channel,然后深入到Channel的源码中,解析其内部的实现机制。

使用案例一:文件遍历和过滤

在我们的使用案例中,我们需要遍历一个文件夹及其所有子文件夹,并过滤出具有特定扩展名的文件。在此,我们使用了C#的Channel来实现这个任务。

首先,我们创建了一个名为EnumerateFilesRecursively的方法,这个方法接受一个文件夹路径作为参数,并返回一个ChannelReader。这个方法中,我们创建了一个有界的Channel,然后在一个单独的任务中遍历指定的文件夹及其所有子文件夹,并将找到的每个文件的路径写入Channel。当遍历完成后,我们关闭Channel的写入端。

ChannelReader<string> EnumerateFilesRecursively(string root, int capacity = 100, CancellationToken token = default)
{var output = Channel.CreateBounded<string>(capacity);async Task WalkDir(string path){IEnumerable<string> files = null, directories = null;try{files = Directory.EnumerateFiles(path);directories = Directory.EnumerateDirectories(path);}catch (Exception ex){Console.WriteLine($"An error occurred: {ex.Message}");}if (files != null){foreach (var file in files){await output.Writer.WriteAsync(file, token);}}if (directories != null)await Task.WhenAll(directories.Select(WalkDir));}Task.Run(async () =>{await WalkDir(root);output.Writer.Complete();}, token);return output.Reader;
}

然后,我们创建了一个名为FilterByExtension的方法,这个方法接受一个ChannelReader和一个扩展名集合作为参数,并返回一个ChannelReader。在这个方法中,我们创建了一个无界的Channel,然后在一个单独的任务中从输入的Channel中读取每个文件路径,检查其扩展名,如果满足条件,就将其转换为FileInfo并写入输出的Channel。当所有的文件都被处理后,我们关闭Channel的写入端。

ChannelReader<FileInfo> FilterByExtension(ChannelReader<string> input, IReadOnlySet<string> exts, CancellationToken token = default)
{var output = Channel.CreateUnbounded<FileInfo>();Task.Run(async () =>{try{await foreach (var file in input.ReadAllAsync(token).ConfigureAwait(false)){var fileInfo = new FileInfo(file);if (exts.Contains(fileInfo.Extension))await output.Writer.WriteAsync(fileInfo, token).ConfigureAwait(false);}}catch (Exception ex){Console.WriteLine($"An error occurred: {ex.Message}");}finally{output.Writer.Complete();}}, token);return output;
}

最后,在Main方法中,我们首先调用EnumerateFilesRecursively方法,遍历指定的文件夹,并得到一个文件路径的Channel。然后,调用FilterByExtension方法,过滤出具有特定扩展名的文件,并得到一个文件信息的Channel。最后,遍历这个Channel,打印出每个文件的全路径。

var fileSource = EnumerateFilesRecursively("D:\\Program Files\\.nuget\\packages");
var sourceCodeFiles =FilterByExtension(fileSource, new HashSet<string> { ".json", ".map", ".dll" });await foreach (var file in sourceCodeFiles.ReadAllAsync().ConfigureAwait(false))
{Console.WriteLine($"{file.FullName}");
}Console.ReadKey();

在这个例子中,可以看到无论是文件的遍历还是过滤,都是并行进行的,并且这两个任务之间通过Channel进行了解耦,使得代码更加简洁和清晰。此外,由于Channel的异步特性,我们的程序在等待数据的时候不会阻塞,从而大大提高了程序的性能和响应性。

使用案例二:Excel读取与翻译内容

在我们的使用案例中,我们需要读取Excel文件,同时将读取的内容处理,调用对应的翻译服务进行翻译,并将翻译结果打印到控制台并存储到新的Excel文件中。为此,我们定义了一个名为ExcelTranslationProvider的类。

ExcelTranslationProvider类

ExcelTranslationProvider类是一个专门处理Excel文件翻译的工具。它主要使用了.NET的Channel来处理异步数据流,从而提高了翻译的效率。以下是该类的代码:

public class ExcelTranslationProvider : TranslationProvider
{public static Translater Translater { get; set; } = Translater.Azure;public static II18NTermTranslateService TranslateService => TranslateServiceProvider.GetTranslateService(Translater);private static ExcelTranslationParameters translationParameters;public static async Task Translate(TranslationParameters parameters){if (parameters is not ExcelTranslationParameters excelParameters)throw new ArgumentException("Invalid parameters for Excel translation.");translationParameters = excelParameters;var translateText = TranslateText(excelParameters.Path);var i = 1;List<TranslationDto> list = new List<TranslationDto>();await foreach (var text in translateText.ReadAllAsync().ConfigureAwait(false)){System.Console.WriteLine($"{i++}、" + text.TranslatText);list.Add(text);}await ExcelUtil.SaveAsAsync(excelParameters.SavePath, list);}private static ChannelReader<TranslationDto> TranslateText(string path){var output = Channel.CreateUnbounded<TranslationDto>();_ = TranslateAndWriteToChannelAsync(path, output.Writer);return output.Reader;}private static async Task TranslateAndWriteToChannelAsync(string path, ChannelWriter<TranslationDto> writer){var query = await ExcelUtil.QueryAsync<TranslationDto>(path, translationParameters.Sheet);var tasks = query.Select(async item =>{try{var res = await TranslateService.TranslateSync(item.Name, "en-US");item.TranslatText = res;await writer.WriteAsync(item);}catch (Exception ex){System.Console.WriteLine($"An error occurred: {ex.Message}");}});await Task.WhenAll(tasks);writer.Complete();}
}
  • Translater和TranslateService:这两个静态属性用于配置和获取翻译服务。Translater是一个枚举类型,表示可用的翻译服务提供者。默认的翻译服务是Azure。TranslateService是一个只读属性,返回一个实现了II18NTermTranslateService接口的翻译服务对象。这个对象是通过TranslateServiceProvider.GetTranslateService(Translater)方法获取的。

  • translationParameters:用于保存翻译参数,这些参数包括源文件的路径、目标文件的路径等。

  • Translate:这个方法首先检查传入的参数是否为ExcelTranslationParameters类型。然后,它调用TranslateText方法开始翻译过程。翻译的结果被保存在一个List列表中,然后写入到Excel文件。

  • TranslateText:它创建了一个无界Channel,并启动了一个异步任务来进行翻译操作并将结果写入到Channel中。无界Channel是一种可以存储任意数量元素的Channel,它是通过Channel.CreateUnbounded()方法创建的。创建Channel后,这个方法返回Channel的读取端,同时启动了一个异步任务TranslateAndWriteToChannelAsync来进行翻译并将结果写入到Channel的中。

  • TranslateAndWriteToChannelAsync:它负责从Excel文件中读取数据,进行翻译,并将翻译结果写入到Channel中。这个方法首先从Excel文件中读取数据,然后为每一条数据创建一个异步翻译任务。所有的翻译任务是并发执行的,使用了Task.WhenAll(tasks)来等待所有的翻译任务完成。完成所有的翻译任务后,这个方法调用writer.Complete()方法来表示没有更多的数据要写入到Channel中。

相关文章:

理解并掌握C#的Channel:从使用案例到源码解读(一)

引言 在C#的并发编程中&#xff0c;Channel是一种非常强大的数据结构&#xff0c;用于在生产者和消费者之间进行通信。本文将首先通过一个实际的使用案例&#xff0c;介绍如何在C#中使用Channel&#xff0c;然后深入到Channel的源码中&#xff0c;解析其内部的实现机制。 使用案…...

如何让git命令仅针对当前目录

背景 我们有时候建的git仓库是这样的&#xff0c;a目录下有b、c、d三个模块&#xff08;文件夹&#xff09;。有时候只想查看b下面的变化&#xff0c;而使用 git status、git diff 的时候会把c和d的变化都列出来&#xff0c;要怎么只查b目录的变化&#xff1f; 操作 要查b目…...

【0223】源码剖析smgr底层设计机制(3)

1. smgr设计机制 PG内核中smgr完整磁盘存储介质的管理是通过下面三部分实现的。 1.1 函数指针结构体 f_smgr 函数指针结构体 f_smgr。 通过该函数指针类型,可完成类似于UNIX系统中的VFD功能,上层只需要调用open()、read()、write()等系统函数,用户不必去关系底层的文件系统…...

Visual Studio 2019 C# winform CefSharp 中播放视频及全屏播放

VS C# winform CefSharp 浏览器控件&#xff0c;默认不支持视频播放&#xff0c;好在有大佬魔改了dll&#xff0c;支持流媒体视频播放。虽然找了很久&#xff0c;好歹还是找到了一个版本100.0.230的dll&#xff08;资源放在文末&#xff09; 首先创建一个项目 第二、引入CefSha…...

天选之子Linux是如何发展起来的?为何对全球IT行业的影响如此之大?

天选之子Linux是如何发展起来的&#xff1f;为何对全球IT行业的影响如此之大&#xff1f; 前言一、UNIX发展史二、Linux发展历史三、开源四、官网五、 企业应用现状六、发行版本 前言 上面这副图是博主历时半小时完成的&#xff0c;给出了Linxu的一些发展背景。球球给位看官老…...

MDK报错:Undefined symbol assert_failed报错解决策略

MDK报错&#xff1a;Undefined symbol assert_failed报错解决策略 &#x1f3af;&#x1fa95;在全网搜索相关MDK编译报错:Error: L6218E: Undefined symbol assert_param (referred from xxx.o). ✨有些问题看似很简单&#xff0c;可能产生的问题是由于不经意的细节原因导致。…...

LLM - Make Causal Mask 构造因果关系掩码

目录 一.引言 二.make_causal_mask 1.完整代码 2.Torch.full 3.torch.view 4.torch.masked_fill_ 5.past_key_values_length 6.Test Main 三.总结 一.引言 Causal Mask 主要用于限定模型的可视范围&#xff0c;防止模型看到未来的数据。在具体应用中&#xff0c;Caus…...

Python函数式编程(一)概念和itertools

Python函数式编程是一种编程范式&#xff0c;它强调使用纯函数来处理数据。函数是程序的基本构建块&#xff0c;并且尽可能避免或最小化可变状态和副作用。在函数式编程中&#xff0c;函数被视为一等公民&#xff0c;可以像值一样传递和存储。 函数式编程概念 编程语言支持通…...

Guava限流器原理浅析

文章目录 基本知识限流器的类图使用示例 原理解析限流整体流程问题驱动1、限流器创建的时候会初始化令牌吗&#xff1f;2、令牌是如何放到桶里的&#xff1f;3、如果要获取的令牌数大于桶里的令牌数会怎么样4、令牌数量的更新会有并发问题吗 总结 实际工作中难免有限流的场景。…...

第四十二章 持久对象和SQL - 用于创建持久类和表的选项

文章目录 第四十二章 持久对象和SQL - 用于创建持久类和表的选项用于创建持久类和表的选项访问数据 第四十二章 持久对象和SQL - 用于创建持久类和表的选项 用于创建持久类和表的选项 要创建持久类及其对应的 SQL 表&#xff0c;可以执行以下任一操作&#xff1a; 使用 IDE …...

集合-ArrayList源码分析(面试)

系列文章目录 1.集合-Collection-CSDN博客​​​​​​ 2.集合-List集合-CSDN博客 3.集合-ArrayList源码分析(面试)_喜欢吃animal milk的博客-CSDN博客 目录 系列文章目录 前言 一 . 什么是ArrayList? 二 . ArrayList集合底层原理 总结 前言 大家好,今天给大家讲一下Arra…...

跨类型文本文件,反序列化与类型转换的思考

文章目录 应用场景序列化 - 对象替换原内容&#xff0c;方便使用编写程序取得结果数组 序列化 - JSON 应用场景 在编写热更新的时候&#xff0c;我发现了一个古早的 ini 文件&#xff0c;记录了许多有用的数据 由于使用的语言年份较新&#xff0c;没有办法较好地对 ini 文件的…...

ubuntu20安装nvidia驱动

1. 查看显卡型号 lspci | grep -i nvidia 我的输出&#xff1a; 01:00.0 VGA compatible controller: NVIDIA Corporation GP104 [GeForce GTX 1080] (rev a1) 01:00.1 Audio device: NVIDIA Corporation GP104 High Definition Audio Controller (rev a1) 07:00.0 VGA comp…...

gma 2 成书计划

随着 gma 2 整体构建完成。下一步计划针对库内所有功能完成一个用户指南&#xff08;非网站&#xff09;。 封皮 主要章节 章节完成度相关链接第 1 章 GMA 概述已完成第 2 章 地理空间数据操作已完成第 3 章 坐标参考系统已完成第 4 章 地理空间制图已完成第 5 章 数学运算模…...

从零手搓一个【消息队列】项目设计、需求分析、模块划分、目录结构

文章目录 一、需求分析1, 项目简介2, BrokerServer 核心概念3, BrokerServer 提供的核心 API4, 交换机类型5, 持久化存储6, 网络通信7, TCP 连接的复用8, 需求分析小结 二、模块划分三、目录结构 提示&#xff1a;是正在努力进步的小菜鸟一只&#xff0c;如有大佬发现文章欠佳之…...

【Spring Cloud】深入探索 Nacos 注册中心的原理,服务的注册与发现,服务分层模型,负载均衡策略,微服务的权重设置,环境隔离

文章目录 前言一、初识 Nacos 注册中心1.1 什么是 Nacos1.2 Nacos 的安装&#xff0c;配置&#xff0c;启动 二、服务的注册与发现三、Nacos 服务分层模型3.1 Nacos 的服务分级存储模型3.2 服务跨集群调用问题3.3 服务集群属性设置3.4 修改负载均衡策略为集群策略 四、根据服务…...

No156.精选前端面试题,享受每天的挑战和学习

🤍 前端开发工程师(主业)、技术博主(副业)、已过CET6 🍨 阿珊和她的猫_CSDN个人主页 🕠 牛客高级专题作者、在牛客打造高质量专栏《前端面试必备》 🍚 蓝桥云课签约作者、已在蓝桥云课上架的前后端实战课程《Vue.js 和 Egg.js 开发企业级健康管理项目》、《带你从入…...

如何在PIL图像和PyTorch Tensor之间进行相互转换,使用pytorch进行PIL和tensor之间的数据转换

目录 引言PIL简介PyTorch和Torchvision简介PIL转换为TensorTensor转换为PIL实例代码和解释结论参考文献 &#x1f4dd; 引言 在计算机视觉领域&#xff0c;使用图像处理库对图像进行预处理是非常常见的。其中&#xff0c;Python Imaging Library&#xff08;PIL&#xff09;以…...

STM32F4X UCOSIII任务消息队列

STM32F4X UCOSIII任务消息队列 任务消息队列和内核消息队列对比内核消息队列内核消息队列 UCOSIII任务消息队列API任务消息队列发送函数任务消息队列接收函数 UCOSIII任务消息队列例程 之前的章节中讲解过消息队列这个机制&#xff0c;UCOSIII除了有内核消息队列之外&#xff0…...

8个居家兼职,帮助自己在家搞副业

越来越多的人开始追求居家工作的机会&#xff0c;无论是为了获得更多收入以改善生活质量&#xff0c;还是为了更好地平衡工作和家庭的关系&#xff0c;居家兼职已成为一种趋势。而在家中从事副业不仅能够为我们带来额外的收入&#xff0c;更重要的是&#xff0c;它可以让我们在…...

管理与系统思维

技术管理者不仅仅需要做事情&#xff0c;还需要以系统思维的方式推动组织变革&#xff0c;从而帮助团队和个人做到更好。原文: Management and Systems Thinking 图片来源: Dall-E "除非管理者考虑到组织的系统性&#xff0c;否则大多数提高绩效的努力都将注定失败。"…...

电死人的是电流还是电压?

先说答案&#xff0c;是电流。 这个有两个派别&#xff0c;一个是电流派&#xff0c;一个是电压派。 举个例子&#xff0c;拿我们的头发或者指甲之类的高电阻物质去接触高压&#xff0c;你会发现基本没有什么作用&#xff1b;还有就是冬天我们脱毛衣的时候&#xff0c;噼里啪啦…...

mac 编译问题记录

1、mac 编译提示 Unsupported option ‘--no-pie‘ Linux 上用 --no-pie mac 上用 -no-pie 2、mac 找不到 malloc.h 使用 #include <sys/malloc.h> Mac上使用malloc函数报错_mac malloc.h-CSDN博客...

centos 7.9同时安装JDK1.8和openjdk11两个版本

1.使用的原因 在服务器上&#xff0c;有些情况因为有一些系统比较老&#xff0c;所以需要使用JDK8版本&#xff0c;但随着时间的发展&#xff0c;新的软件出来&#xff0c;一般都会使用比较新的JDK版本。所以就出现了我们标题的需求&#xff0c;一个系统内同时安装两个不同的版…...

【JavaEE】HTML

JavaWeb HTML 超文本标记语言 超文本&#xff1a;文本、声音、图片、视频、表格、连接标记&#xff1a;有许许多多的标签组成 vscode开发工具搭建 因为我使用的IDEA是社区版&#xff0c;代码高亮补全缩进都有些问题&#xff0c;使用vscode是最好的选择~ 安装 Visual Stu…...

【数据结构--八大排序】之堆排序

&#x1f490; &#x1f338; &#x1f337; &#x1f340; &#x1f339; &#x1f33b; &#x1f33a; &#x1f341; &#x1f343; &#x1f342; &#x1f33f; &#x1f344;&#x1f35d; &#x1f35b; &#x1f364; &#x1f4c3;个人主页 &#xff1a;阿然成长日记 …...

c# 中的类

反射 Activator.CreateInstance class Program {static void Main(string[] args){//反射Type t typeof(Student);object o Activator.CreateInstance(t, 1, "FJ");Student stu o as Student;Console.WriteLine(stu.Name);//动态编程dynamic stu2 Activator.Cre…...

基于单片机的煤气泄漏检测报警装置设计

一、项目介绍 煤气泄漏是一种常见的危险情况&#xff0c;可能导致火灾、爆炸和人员伤亡。为了及时发现煤气泄漏并采取相应的安全措施&#xff0c;设计了一种基于单片机的煤气泄漏检测报警装置。 主控芯片采用STM32F103C8T6作为主控芯片&#xff0c;具有强大的计算和控制能力。…...

[导弹打飞机H5动画制作] 导弹每次飞行的随机路线制作

技术核心提示: 第一步:检测引导层插件是否具备,如果没有手工添加: createjs.MotionGuidePlugin.install(); 第二步:增加全局变量: var fValue=0; var iOddEven =0; var missileObj=null; 第三步:填写 第一帧 代码: if (missileObj)stage.removeChild(missileObj);missile…...

OpenCV实现FAST算法角点检测 、ORB算法特征点检测

目录 1 Fast算法 1.1 Fast算法原理 1.2 实现办法 1.2.1 机器学习的角点检测器 1.2.2 非极大值抑制 1.3 代码实现 1.4 结果展示 2 &#xff0c;ORB算法 2.1代码实现 2.2 结果展示 1 Fast算法 1.1 Fast算法原理 1.2 实现办法 1.2.1 机器学习的角点检测器 1.2.2 …...

美团网网站建设 费用/长春网站搭建

一、Web开发介绍 目前Web开发属于Browser/Server模式&#xff0c;简称BS架构&#xff0c;开发语言有&#xff08;Python、PHP、Java …&#xff09;。基于Python的Web工作原理如下&#xff1a; 二、框架介绍 1.什么是框架&#xff1f; 软件框架就是为实现或完成某种软件开发…...

深圳网站制作网站建设/seo工作前景如何

为什么特别讨论二叉树的遍历 之前处理的都是线性结构&#xff0c;线性结构的遍历只有一条路径&#xff0c;遍历起来十分简单。 二叉树是非线性结构&#xff0c;每个结点可能有两个子树 / 后继&#xff0c;因此需要确定遍历的方法&#xff0c; 使二叉树上的所有结点都能排在一个…...

郑州市装修公司哪家好/深圳市seo点击排名软件价格

基本思想&#xff1a;贪心思想掌握的还不是很好&#xff0c;在枚举情况漏了一种&#xff1a;010111此时需要翻两次&#xff1b;如果使用贪心策略&#xff0c;则是先寻找当下最优解&#xff0c;即&#xff1a;直接遇到不一样的直接翻&#xff0c;之后进行后续的判断&#xff1b;…...

做网站怎么买断源码/如何快速推广

该楼层疑似违规已被系统折叠 隐藏此楼查看此楼看下 GtkEntry 的源码不就知道了。。。gtk_entry_get_display_text...if (end_pos < start_pos)return g_strdup ("");else if (priv->visible){start g_utf8_offset_to_pointer (text, start_pos);end g_utf8_o…...

wordpress常规地址改错了怎么办/中囯军事网

一、单选题1、计算机中所有的数据都是用(C)数来表示A八进制B十六进制C二进制D十进制2、第二代电子计算机采用(B)作为主要器件A电子管B晶体管C小规模集成电路D大规模及和电路3、计算机语言可分为机器语言&#xff0c;(C)和高级语言AC语言BBasic语言C汇编语言DPASCAL语言4、计算机…...

web网站建设与计划论文/大连网站优化

点击上方“程序员小灰”&#xff0c;选择“置顶公众号”有趣有内涵的文章第一时间送达&#xff01;本文授权转载自 CSDN 与言则整理圣诞将至&#xff0c;还不赶快微信官方 求顶圣诞帽~~点开朋友圈&#xff0c;你会发现许多好友的头像&#xff0c;都戴着一顶红色的圣诞帽&#x…...