目录简介Channel的诞生背景核心概念模型创建Channel写入Channel读取Channel完整示例实践练习核心要点简介你可能早已听说过async、await任务等概念但在多线程间安全传输数据时大多数人还是给List加个锁然后祈祷系统不会崩溃。现在让我们认识Channel——.NET并发编程中被低估的王者。这是C#通道系列教程的第一部分记得订阅以便接收后续更新。可以把Channel想象成线程安全的邮箱一端投递信件另一端取出信件。无需锁机制天生支持异步操作。本文将深入浅出展示生产者如何轻松向消费者传递消息既不费力也不消耗CPU。读完本篇你不仅能掌握Channel的工作原理还能为后续更复杂的模式打下基础。Channel的诞生背景坦白说如果你用C#编写多线程代码大概率曾与ConcurrentQueue、BlockingCollection纠缠过或手动给List加锁。这些方案确实能用...但也就勉强能用。当你需要非阻塞线程的异步操作时怎么办当单个生产者需要向异步运行的消费者发送数百条消息时又该如何Channel优雅地解决了这些问题它提供• 生产者与消费者间的线程安全通信• 原生异步API无需手动阻塞线程• 明确的读写分离ChannelWriter与ChannelReader就像现实中的邮箱一端投信另一端取信即使多线程同时操作也不会引发混乱。核心概念模型接触代码前先建立最简心智模型生产者 → Channel → 消费者• 生产者向通道推送消息• Channel安全存储消息并处理线程同步• 消费者从通道读取消息支持异步后续我们会扩展至多生产者/消费者场景目前先聚焦单读写器模式。创建Channel.NET让通道创建变得轻而易举using System; using System.Threading.Channels; using System.Threading.Tasks; var channel Channel.CreateUnboundedint(); // 无边界通道 Console.WriteLine(Channel created!);仅需一行代码你就获得了可用的通信邮箱。现在你拥有了包含两个核心组件的Channel• channel.Writer → 生产者写入端• channel.Reader → 消费者读取端写入Channel来看生产者的实际运作async Task ProduceAsync(ChannelWriterint writer) { for (int i 1; i 5; i) { await writer.WriteAsync(i); // 将数据存入通道 Console.WriteLine($Produced: {i}); await Task.Delay(500); // 模拟工作负载 } writer.Complete(); // 发出完成信号 }注意• WriteAsync体现通道的异步优先特性• Task.Delay仅用于模拟实际生产中的处理过程• writer.Complete()通知消费者数据流已终止读取Channel消费者端的实现async Task ConsumeAsync(ChannelReaderint reader) { await foreach (var item in reader.ReadAllAsync()) { Console.WriteLine($Consumed: {item}); } }关键特性• ReadAllAsync()自动等待新项目直到通道关闭• 无需锁机制无需自旋循环• 生产者调用Complete()后消费者自动结束完整示例以下是整合生产者与消费者的最小控制台程序using System; using System.Threading.Channels; using System.Threading.Tasks; classProgram { static async Task Main() { var channel Channel.CreateUnboundedint(); var producer ProduceAsync(channel.Writer); var consumer ConsumeAsync(channel.Reader); await Task.WhenAll(producer, consumer); } static async Task ProduceAsync(ChannelWriterint writer) { for (int i 1; i 5; i) { await writer.WriteAsync(i); Console.WriteLine($Produced: {i}); await Task.Delay(500); // 模拟工作负载 } writer.Complete(); } static async Task ConsumeAsync(ChannelReaderint reader) { awaitforeach (var item in reader.ReadAllAsync()) { Console.WriteLine($Consumed: {item}); } } }运行后将看到数字几乎同步被生产和消费。这个简洁优雅的示例完美诠释了核心概念。实践练习请尝试1. 创建字符串消息通道2. 生产包含你喜爱名言的五条消息3. 异步消费并打印这些消息4. 在生产者中添加Task.Delay模拟工作负载这将帮助你巩固生产者→通道→消费者的基础模式。核心要点• Channel是线程安全的异步优先邮箱• ChannelWriter负责写入ChannelReader负责读取• 务必调用Complete()声明数据流结束• 从单生产者/消费者入门逐步深入恭喜你已成功通过Channel传递首条消息且未使用任何锁机制或担心线程安全。你已见识到生产者如何异步传递数据给消费者理解了ChannelWriter与ChannelReader的协同工作机制也明确了调用Complete()的重要性。这就像搭建自己的传送带物品从一端进入从另一端送出全程无需人工干预。初级阶段最重要的是保持简单单生产者、单消费者、流畅传输。后续我们将增加更多操作员处理反压机制探索让Channel在真实.NET应用中大放异彩的高级异步模式。引入地址