C#如何使用Channel C#通道实现异步通信
技术百科
星降
发布时间:2026-01-02
浏览: 次 Channel 是 .NET 轻量、线程安全的异步生产者-消费者通信原语,支持无界/有界模式,提供 WriteAsync/ReadAllAsync 等简洁 API,适用于后台任务、管道处理等场景,需调用 Complete() 通知结束,有界容量需权衡吞吐与延迟。
c#通道实现异步通信">
Channel
创建和配置 Channel
Channel 有无界(Unbounded)和有界(Bounded)两种类型,选择取决于你对内存控制和背压(backpressure)的需求:
-
无界 Channel:缓冲区无限增长,适合吞吐优先、不担心内存溢出的场景(如日志采集)
var channel = Channel.CreateUnbounded(); -
有界 Channel:指定容量,写入时若满则默认等待(可设为丢弃或抛异常),适合需要流量控制的场景(如实时消息队列)
var channel = Channel.CreateBounded(capacity: 100);
写入数据(Producer)
使用 Writer 写入,支持同步和异步方式。推荐用 WriteAsync 配合 await,尤其对有界 Channel 能自然等待空闲空间:
- 写入单个值:await channel.Writer.WriteAsync("hello");
- 批量写入(高效):await channel.Writer.WriteAsync(new[] {"a", "b", "c"});
- 标记写入完成(通知消费者停止读取):channel.Writer.Complete();
读取数据(Consumer)
使用 Reader 读取,核心是 ReadAsync —— 它会挂起直到有数据或 Channel 关闭:
- 基础读取循环:
while (await channel.Reader.WaitToReadAsync())
while (channel.Reader.TryRead(out var item))
Console.WriteLine(item); - 更简洁写法(推荐):
await foreach (var item in channel.Reader.ReadAllAsync())
Console.WriteLine(item); - 注意:ReadAllAsync 会在 Writer.Complete() 后自动退出循环,无需手动判断。
组合多个 Channel 实现管道
Channel 天然适合构建链式处理管道。例如:接收原始日志 → 过滤 → 格式化 → 输出:
- 启动一个后台任务做过滤:
_ = Task.Run(async () => {
await foreach (var line in input.Reader.ReadAllAsync())
if (line.Contains("ERROR"))
await filtered.Writer.WriteAsync(line);
filtered.Writer.Complete();
}); - 后续环节消费
filteredChannel,彼此完全解耦,且自动异步流控。
基本上就这些。Channel 不复杂但容易忽略两点:一是别忘了调用 Complete() 告诉消费者“没新数据了”,二是有界 Channel 的容量设置要结合实际吞吐和延迟容忍度来权衡。
# ai
# 会在
# 是有
# 多个
# 它会
# 链式
# 适用于
# 一是
# 设为
# input
# 循环
# Error
# 并发
# String
# if
# int
# c#
# .net
# console
# 线程
# 异步
# 事件
# red
# var
# foreach
# while
# channel
# 别忘了
# 无界
相关栏目:
<?muma
$count = M('archives')->where(['typeid'=>$field['id']])->count();
?>
【
AI推广<?muma echo $count; ?>
】
<?muma
$count = M('archives')->where(['typeid'=>$field['id']])->count();
?>
【
SEO优化<?muma echo $count; ?>
】
<?muma
$count = M('archives')->where(['typeid'=>$field['id']])->count();
?>
【
技术百科<?muma echo $count; ?>
】
<?muma
$count = M('archives')->where(['typeid'=>$field['id']])->count();
?>
【
谷歌推广<?muma echo $count; ?>
】
<?muma
$count = M('archives')->where(['typeid'=>$field['id']])->count();
?>
【
百度推广<?muma echo $count; ?>
】
<?muma
$count = M('archives')->where(['typeid'=>$field['id']])->count();
?>
【
网络营销<?muma echo $count; ?>
】
<?muma
$count = M('archives')->where(['typeid'=>$field['id']])->count();
?>
【
案例网站<?muma echo $count; ?>
】
<?muma
$count = M('archives')->where(['typeid'=>$field['id']])->count();
?>
【
精选文章<?muma echo $count; ?>
】
相关推荐
- PHP的FastAdmin架构适合二次开发吗_特点
- MAC怎么使用表情符号面板_MAC Emoji快捷
- MySQL 中使用 IF 和 CASE 实现查询字
- Win11怎么设置ip地址_Windows 11手
- Win11搜索不到蓝牙耳机怎么办 Win11蓝牙驱
- Mac系统更新下载慢或失败怎么办_解决macOS升
- php8.4新语法match怎么用_php8.4m
- c# 在ASP.NET Core中管理和取消后台任
- MAC如何启用访达侧边栏显示_MAC Finder
- Win10怎样设置多显示器_Win10多显示器扩展
- c++怎么使用类型萃取type_traits_c+
- php文件怎么变mp4保存_php输出视频流保存为
- Win11怎么设置麦克风权限_允许应用访问Win1
- Win11怎么设置环境变量_Win11配置Path
- Win11关机界面怎么改_Win11自定义关机画面
- Windows10怎样设置家长控制_Windows
- 如何在 ACF 中正确更新嵌套多层的 Group
- Win11如何设置计划任务 Win11定时执行程序
- ACF 教程:正确更新嵌套在多层 Group 字段
- Win11怎么查看已连接wifi密码 Win11查
- 如何在Mac上搭建Golang开发环境_使用Hom
- 如何使用Golang开发简单的聊天室消息存储_Go
- Win11怎么关闭系统声音_Win11系统提示音静
- Go 中实现 Python urllib.quot
- Win11快速助手怎么用_Win11远程协助连接教
- MAC如何隐藏文件夹及文件_MAC终端命令隐藏与第
- Win10怎么关闭自动更新错误重启 Win10策略
- Windows蓝屏错误0x0000002C怎么解决
- Win11怎么开启游戏工具栏_Windows11
- 如何使用Golang实现函数指针_函数变量与回调示
- Python迭代器生成器进阶教程_节省内存与懒加载
- Win11怎么更改鼠标指针方案_Windows11
- 如何在Golang中实现基础配置管理功能_Gola
- Win11怎么设置系统还原_Windows11系统
- C#怎么创建控制台应用 C# Console Ap
- 如何在 Go 中创建包含映射(map)的切片(sl
- Win11怎么设置应用分屏_Windows11贴靠
- Win11文件夹预览图不显示怎么办_Win11缩略
- php本地部署后session无法保存_sessi
- 如何用列表一次性对 DataFrame 的指定列应
- 如何解决Windows时间不准的问题?(自动同步设
- C++中的协变与逆变是什么?C++函数指针与返回类
- 如何用::实现单例模式_php静态方法与作用域操作
- Win10系统字体模糊怎么办_Windows10高
- Win11怎么设置默认邮件客户端 Win11修改M
- 零基础学会Python自动化办公_高效处理Exce
- Mac如何彻底清理浏览器缓存?(Safari与Ch
- 网站内页做seo排名怎么做?
- MAC如何安装Git版本控制工具_MAC开发环境配
- Go语言中slice追加操作的底层共享机制详解

c/ReadAllAsync 等简洁 API,适用于后台任务、管道处理等场景,需调用 Complete() 通知结束,有界容量需权衡吞吐与延迟。
QQ客服