0

0

c# 生产者消费者模式的实现 c# BlockingCollection 和 Channel 哪个好

煙雲

煙雲

发布时间:2026-01-31 08:50:02

|

292人浏览过

|

来源于php中文网

原创

BlockingCollection适合同步场景,Channel更适合异步流控;前者基于线程阻塞,后者支持async/await、零分配和背压控制,选择取决于阻塞模型而非绝对优劣。

c# 生产者消费者模式的实现 c# blockingcollection 和 channel 哪个好

BlockingCollection 适合同步场景,Channel 更适合异步流控

如果你的生产者和消费者主要跑在 Task.Run 或线程池里,且不强依赖 async/awaitBlockingCollection 简单直接、调试友好;但一旦涉及高吞吐异步 I/O(比如从网络流持续读取并处理),Channel 的零分配、可取消、支持 async 消费等特性就明显占优。

关键区别不在“谁更好”,而在“谁更贴合你的阻塞模型”:前者是同步阻塞 + 线程等待,后者是异步等待 + 可选背压。

BlockingCollection 的典型误用:忘了设置 BoundedCapacity

默认构造的 BlockingCollection 是无界队列,内存可能无限增长,尤其当生产速度远超消费速度时。线上服务容易因此 OOM。

  • 务必显式传入 BoundedCapacity,例如:new BlockingCollection(new ConcurrentQueue(), 1000)
  • 配合 TryAddTryTake 做非阻塞试探,避免死锁或线程卡死
  • 调用 CompleteAdding() 后,GetConsumingEnumerable() 才会退出循环 —— 忘记这步会导致消费者永远空转

Channel 的三个易踩坑点

Channel 看似轻量,但行为比表面复杂,尤其对刚从 BlockingCollection 迁移的人:

HaiSnap
HaiSnap

一站式AI应用开发和部署工具

下载
  • 默认 Channel.CreateUnbounded() 不提供背压,和无界 BlockingCollection 一样危险;要用 Channel.CreateBounded(new BoundedChannelOptions(1000))
  • Writer.TryWrite() 在满时返回 false,但 Writer.WriteAsync() 会 await 直到有空间 —— 若没配超时或取消,可能永久挂起
  • Reader.ReadAsync() 在 Channel 关闭后抛 InvalidOperationException,不是返回 defaultnull;正确做法是用 await foreach (var item in channel.Reader.ReadAllAsync(cancellationToken))

性能与兼容性:.NET 版本和分配压力决定选择

BlockingCollection 从 .NET 4.0 就存在,完全兼容桌面应用和旧版 ASP.NET;Channel 是 .NET Core 2.1+ 引入,需注意目标框架。

  • 高频小对象写入(如每毫秒千次)下,ChannelWriteAsync 几乎零分配,而 BlockingCollection.Add() 每次都可能触发内部锁和通知开销
  • 若项目已重度使用 System.Threading.Channels(比如 ASP.NET Core 的底层管道、gRPC 流),继续用 Channel 能保持语义一致
  • 调试时,BlockingCollection 的当前 CountIsAddingCompleted 属性一目了然;Channel 的状态需查 Reader.Completion.IsCompletedWriter.Completion.IsCompleted,稍绕
var channel = Channel.CreateBounded(new BoundedChannelOptions(100)
{
    FullMode = BoundedChannelFullMode.Wait,
    SingleReader = true,
    SingleWriter = true
});

// 生产者(async)
_ = Task.Run(async () =>
{
    for (int i = 0; i < 1000; i++)
    {
        await channel.Writer.WriteAsync($"item-{i}");
        await Task.Delay(1);
    }
    channel.Writer.Complete();
});

// 消费者(async)
_ = Task.Run(async () =>
{
    await foreach (var item in channel.Reader.ReadAllAsync())
    {
        Console.WriteLine(item);
    }
});

真正难的不是选哪个类型,而是想清楚:你的“消费者”是主动拉取还是被动通知?是否允许延迟?能否接受某次写入失败而不崩溃?这些决策点比 API 差异更影响最终稳定性。

热门AI工具

更多
DeepSeek
DeepSeek

幻方量化公司旗下的开源大模型平台

豆包大模型
豆包大模型

字节跳动自主研发的一系列大型语言模型

通义千问
通义千问

阿里巴巴推出的全能AI助手

腾讯元宝
腾讯元宝

腾讯混元平台推出的AI助手

文心一言
文心一言

文心一言是百度开发的AI聊天机器人,通过对话可以生成各种形式的内容。

讯飞写作
讯飞写作

基于讯飞星火大模型的AI写作工具,可以快速生成新闻稿件、品宣文案、工作总结、心得体会等各种文文稿

即梦AI
即梦AI

一站式AI创作平台,免费AI图片和视频生成。

ChatGPT
ChatGPT

最最强大的AI聊天机器人程序,ChatGPT不单是聊天机器人,还能进行撰写邮件、视频脚本、文案、翻译、代码等任务。

相关专题

更多
c语言中null和NULL的区别
c语言中null和NULL的区别

c语言中null和NULL的区别是:null是C语言中的一个宏定义,通常用来表示一个空指针,可以用于初始化指针变量,或者在条件语句中判断指针是否为空;NULL是C语言中的一个预定义常量,通常用来表示一个空值,用于表示一个空的指针、空的指针数组或者空的结构体指针。

237

2023.09.22

java中null的用法
java中null的用法

在Java中,null表示一个引用类型的变量不指向任何对象。可以将null赋值给任何引用类型的变量,包括类、接口、数组、字符串等。想了解更多null的相关内容,可以阅读本专题下面的文章。

458

2024.03.01

counta和count的区别
counta和count的区别

Count函数用于计算指定范围内数字的个数,而CountA函数用于计算指定范围内非空单元格的个数。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

198

2023.11.20

php中foreach用法
php中foreach用法

本专题整合了php中foreach用法的相关介绍,阅读专题下面的文章了解更多详细教程。

76

2025.12.04

线程和进程的区别
线程和进程的区别

线程和进程的区别:线程是进程的一部分,用于实现并发和并行操作,而线程共享进程的资源,通信更方便快捷,切换开销较小。本专题为大家提供线程和进程区别相关的各种文章、以及下载和课程。

525

2023.08.10

Golang channel原理
Golang channel原理

本专题整合了Golang channel通信相关介绍,阅读专题下面的文章了解更多详细内容。

248

2025.11.14

golang channel相关教程
golang channel相关教程

本专题整合了golang处理channel相关教程,阅读专题下面的文章了解更多详细内容。

344

2025.11.17

default gateway怎么配置
default gateway怎么配置

配置default gateway的步骤:1、了解网络环境;2、获取路由器IP地址;3、登录路由器管理界面;4、找到并配置WAN口设置;5、配置默认网关;6、保存设置并退出;7、检查网络连接是否正常。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

223

2023.12.07

2026赚钱平台入口大全
2026赚钱平台入口大全

2026年最新赚钱平台入口汇总,涵盖任务众包、内容创作、电商运营、技能变现等多类正规渠道,助你轻松开启副业增收之路。阅读专题下面的文章了解更多详细内容。

8

2026.01.31

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
10分钟--Midjourney创作自己的漫画
10分钟--Midjourney创作自己的漫画

共1课时 | 0.1万人学习

Midjourney 关键词系列整合
Midjourney 关键词系列整合

共13课时 | 0.9万人学习

AI绘画教程
AI绘画教程

共2课时 | 0.2万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号