0

0

c# 在 C# 中模拟 goroutine 和 channel 的模式

月夜之吻

月夜之吻

发布时间:2026-01-27 11:16:02

|

661人浏览过

|

来源于php中文网

原创

用 Task + Channel 替代 goroutine + channel 的核心思路是:以 async/await 模拟 goroutine 的异步并发,用线程安全、真异步的 Channel 替代 channel;避免 BlockingCollection 和盲目 Task.Run,正确处理关闭、取消与资源清理。

c# 在 c# 中模拟 goroutine 和 channel 的模式

Task + Channel 替代 goroutine + channel 的核心思路

Go 的 goroutine 本质是轻量级协作式并发单元,C# 没有语言级等价物,但 Task(配合 async/await)在绝大多数 I/O 密集场景下能达到相似效果:高并发、低开销、自动调度。而 Go 的 channel 在 .NET 6+ 中已有原生替代 —— System.Threading.Channels.Channel,它线程安全、支持异步读写、可配置缓冲策略,是目前最贴近的实现。

Channel 的创建与基础用法区别BlockingCollection

很多人第一反应是用 BlockingCollection,但它基于锁 + 阻塞,不支持真正的异步等待(TakeAsync 是伪异步),且无法取消;而 ChannelWriter.WriteAsync()Reader.ReadAsync() 是真异步、可取消、无锁(单生产者/单消费者模式下)。

  • 创建无界 channel:
    var channel = Channel.CreateUnbounded();
  • 创建带容量限制的 channel:
    var channel = Channel.CreateBounded(new BoundedChannelOptions(100) { FullMode = BoundedChannelFullMode.Wait });
  • 写入必须检查是否完成:
    await channel.Writer.WriteAsync("hello"); // 不要忽略返回值
  • 读取需处理关闭信号:
    while (await channel.Reader.WaitToReadAsync()) { if (channel.Reader.TryRead(out var msg)) { /* 处理 msg */ } }

模拟 goroutine 启动:别直接 Task.Run,优先用 async + await

Go 的 go fn() 是隐式启动,C# 若盲目套用 Task.Run(() => { ... }),会把本该异步的 I/O 操作强行拉到线程池,浪费资源,还可能引发死锁(尤其在 UI 或 ASP.NET 同步上下文里)。正确做法是让工作函数本身是 async Task,再用 Task.Run 包裹仅当它含 CPU 密集逻辑时。

  • I/O 密集型(如 HTTP 请求、文件读取):
    async Task WorkerAsync(ChannelReader reader) { while (await reader.WaitToReadAsync()) { if (reader.TryRead(out var msg)) { await SomeHttpCallAsync(msg); } } }
  • CPU 密集型(如图像处理)才考虑 Task.Run
    Task.Run(() => HeavyCompute(msg));
  • 启动多个“goroutine”风格协程:
    _ = WorkerAsync(channel.Reader); _ = WorkerAsync(channel.Reader); // 注意:这里用 _ 忽略 Task 引用,实际应妥善管理生命周期

关闭 channel 和清理资源的常见漏点

Go 的 close(ch) 对应 C# 的 channel.Writer.Complete(),但容易被忽略的是:一旦调用 Complete(),后续所有 WriteAsync 都会抛 InvalidOperationException;且 Reader 不会自动退出循环,必须靠 WaitToReadAsync() 返回 false 才知道 channel 已关闭并写入完毕。

  • 生产者结束前务必调用:
    channel.Writer.Complete();
  • 消费者循环中必须检查 WaitToReadAsync() 返回值:
    while (await channel.Reader.WaitToReadAsync()) { /* ... */ } // 循环退出即表示 channel 关闭且无更多数据
  • 若需等待所有消费者完成,不能只等 channel.Reader.Completion,而应单独跟踪 Task 实例并 await Task.WhenAll(...)

真正难处理的是跨多层嵌套的取消和超时——Channel 本身不持有 CancellationToken,所有 WriteAsync/ReadAsync 调用都得显式传入,漏一个就可能卡死。这点比 Go 的 channel 更易出错。

热门AI工具

更多
DeepSeek
DeepSeek

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

豆包大模型
豆包大模型

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

通义千问
通义千问

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

腾讯元宝
腾讯元宝

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

文心一言
文心一言

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

讯飞写作
讯飞写作

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

即梦AI
即梦AI

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

ChatGPT
ChatGPT

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

相关专题

更多
堆和栈的区别
堆和栈的区别

堆和栈的区别:1、内存分配方式不同;2、大小不同;3、数据访问方式不同;4、数据的生命周期。本专题为大家提供堆和栈的区别的相关的文章、下载、课程内容,供大家免费下载体验。

395

2023.07.18

堆和栈区别
堆和栈区别

堆(Heap)和栈(Stack)是计算机中两种常见的内存分配机制。它们在内存管理的方式、分配方式以及使用场景上有很大的区别。本文将详细介绍堆和栈的特点、区别以及各自的使用场景。php中文网给大家带来了相关的教程以及文章欢迎大家前来学习阅读。

575

2023.08.10

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

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

502

2023.08.10

Golang channel原理
Golang channel原理

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

248

2025.11.14

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

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

344

2025.11.17

http500解决方法
http500解决方法

http500解决方法有检查服务器日志、检查代码错误、检查服务器配置、检查文件和目录权限、检查资源不足、更新软件版本、重启服务器或寻求专业帮助等。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

409

2023.11.09

http请求415错误怎么解决
http请求415错误怎么解决

解决方法:1、检查请求头中的Content-Type;2、检查请求体中的数据格式;3、使用适当的编码格式;4、使用适当的请求方法;5、检查服务器端的支持情况。更多http请求415错误怎么解决的相关内容,可以阅读下面的文章。

418

2023.11.14

HTTP 503错误解决方法
HTTP 503错误解决方法

HTTP 503错误表示服务器暂时无法处理请求。想了解更多http错误代码的相关内容,可以阅读本专题下面的文章。

2208

2024.03.12

Python 自然语言处理(NLP)基础与实战
Python 自然语言处理(NLP)基础与实战

本专题系统讲解 Python 在自然语言处理(NLP)领域的基础方法与实战应用,涵盖文本预处理(分词、去停用词)、词性标注、命名实体识别、关键词提取、情感分析,以及常用 NLP 库(NLTK、spaCy)的核心用法。通过真实文本案例,帮助学习者掌握 使用 Python 进行文本分析与语言数据处理的完整流程,适用于内容分析、舆情监测与智能文本应用场景。

10

2026.01.27

热门下载

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

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
Go 教程
Go 教程

共32课时 | 4.2万人学习

Go语言实战之 GraphQL
Go语言实战之 GraphQL

共10课时 | 0.8万人学习

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

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