news 2026/7/15 1:11:37

C#高级:使用ConcurrentQueue做一个简易进程内通信的消息队列

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
C#高级:使用ConcurrentQueue做一个简易进程内通信的消息队列

文章目录

  • 一、简介
  • 二、使用场景
  • 三、好处
  • 四、代码
  • 总结

一、简介

使用ConcurrentQueue实现线程安全的进程内消息队列,支持多生产者/消费者模式。

二、使用场景

多线程间数据交换、异步任务处理、日志缓冲等需要线程安全队列的场景。

三、好处

  • 线程安全:内置锁机制,无需额外同步
  • 高性能:无锁设计减少竞争
  • 易用性强:实例绑定Key,简化队列管理

四、代码

usingSystem;usingSystem.Collections.Concurrent;usingSystem.Collections.Generic;usingSystem.Linq;usingSystem.Threading;usingSystem.Threading.Tasks;/// <summary>/// 简易队列管理器(实例绑定唯一Key,无需重复传参)/// </summary>/// <typeparam name="T">队列元素类型</typeparam>publicclassEasyQueue<T>:IDisposable{// 静态字典:全局管理所有Key对应的队列(保证Key唯一)privatestaticreadonlyConcurrentDictionary<string,ConcurrentQueue<T>>_globalQueueDict=new();// 实例专属Key(创建实例时指定,后续操作无需传参)publicstringQueueKey{get;}// 实例绑定的队列(避免每次从全局字典获取)privateConcurrentQueue<T>_boundQueue;/// <summary>/// 构造函数:注册Key并绑定专属队列(核心优化点)/// </summary>/// <param name="queueKey">队列唯一标识(注册Key)</param>/// <exception cref="ArgumentNullException">Key为空时抛出</exception>publicEasyQueue(stringqueueKey){if(string.IsNullOrWhiteSpace(queueKey))thrownewArgumentNullException(nameof(queueKey),"队列Key不能为空或空白");QueueKey=queueKey;// 注册Key:不存在则创建新队列,存在则绑定已有队列(线程安全)_boundQueue=_globalQueueDict.GetOrAdd(queueKey,_=>newConcurrentQueue<T>());}#region核心方法(无需传Key,直接操作实例绑定的队列)/// <summary>/// 单个元素入队(实例方法,无需传Key)/// </summary>/// <param name="item">要入队的元素</param>publicvoidEnqueue(Titem){_boundQueue.Enqueue(item);}/// <summary>/// 批量元素入队(实例方法,无需传Key)/// </summary>/// <param name="items">要入队的元素列表</param>/// <exception cref="ArgumentNullException">列表为空时抛出</exception>publicvoidEnqueue(List<T>items){if(items==null||items.Count==0)thrownewArgumentNullException(nameof(items),"入队元素列表不能为空或空列表");foreach(variteminitems){_boundQueue.Enqueue(item);}}/// <summary>/// 出队(实例方法,无需传Key)/// </summary>/// <param name="item">出队的元素(队列为空时返回default(T))</param>/// <returns>是否出队成功(true=成功,false=队列为空)</returns>publicboolDequeue(outTitem){return_boundQueue.TryDequeue(outitem);}/// <summary>/// 查询队列所有元素(实例方法,无需传Key)/// </summary>/// <returns>队列元素列表(队列为空返回空List)</returns>publicList<T>GetQueueItems(){return_boundQueue.ToList();}#endregion#region扩展实用方法(实例级,无需传Key)/// <summary>/// 判断当前实例绑定的队列是否为空/// </summary>publicboolIsEmpty=>_boundQueue.IsEmpty;/// <summary>/// 获取当前队列的元素数量/// </summary>publicintCount=>_boundQueue.Count;/// <summary>/// 清空当前队列/// </summary>publicvoidClear(){while(_boundQueue.TryDequeue(out_)){}}/// <summary>/// 静态方法:移除全局字典中的指定Key(注销队列)/// </summary>/// <param name="queueKey">要注销的Key</param>/// <returns>是否注销成功</returns>publicstaticboolUnregisterQueue(stringqueueKey){if(string.IsNullOrWhiteSpace(queueKey))thrownewArgumentNullException(nameof(queueKey));return_globalQueueDict.TryRemove(queueKey,out_);}/// <summary>/// 静态方法:查询全局已注册的所有队列Key/// </summary>/// <returns>所有Key的列表</returns>publicstaticList<string>GetAllRegisteredKeys(){return_globalQueueDict.Keys.ToList();}#endregion#region资源释放privatebool_disposed=false;protectedvirtualvoidDispose(booldisposing){if(!_disposed){if(disposing){// 释放实例时清空绑定的队列(可选,根据业务需求调整)Clear();}_disposed=true;}}publicvoidDispose(){Dispose(true);GC.SuppressFinalize(this);}#endregion}classProgram{staticvoidMain(string[]args){// 定义队列KeyconststringtestKey="MultiThreadQueue";// ========== 线程1:生产数据(入队) ==========TaskproduceTask=Task.Run(()=>{// 创建生产端实例(绑定testKey)varproducerQueue=newEasyQueue<int>(testKey);for(inti=1;i<=100;i++){producerQueue.Enqueue(i);Console.WriteLine($"【生产线程】入队:{i}");Thread.Sleep(1000);// 模拟生产耗时}Console.WriteLine("【生产线程】生产完成!");});// ========== 线程2:消费数据(出队) ==========TaskconsumeTask=Task.Run(()=>{// 创建消费端实例(绑定同一个testKey)varconsumerQueue=newEasyQueue<int>(testKey);intconsumeCount=0;// 循环消费,直到生产完成且队列为空while(!produceTask.IsCompleted||!consumerQueue.IsEmpty){if(consumerQueue.Dequeue(outintitem)){consumeCount++;Console.WriteLine($"【消费线程】出队:{item}");}else{Thread.Sleep(5);// 队列为空时短暂等待,避免空轮询}}Console.WriteLine($"【消费线程】消费完成!共消费{consumeCount}个元素");});// 等待所有线程完成Task.WaitAll(produceTask,consumeTask);Console.WriteLine("\n所有操作完成!");}}

总结

通过ConcurrentQueue和ConcurrentDictionary实现了一个线程安全的进程内消息队列。该方案支持Key绑定机制简化队列管理,提供完整的生产消费示例,适用于多线程数据交换场景,具备高性能和易用性特点。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/7/8 7:37:43

XART实战:用AI生成动态艺术网站的完整案例

快速体验 打开 InsCode(快马)平台 https://www.inscode.net输入框内输入如下内容&#xff1a; 在XART平台上创建一个动态艺术网站项目&#xff0c;要求能够根据用户交互&#xff08;如鼠标移动、点击&#xff09;实时生成艺术图案。网站应包含以下功能&#xff1a;1&#xff…

作者头像 李华
网站建设 2026/7/1 13:12:17

5分钟玩转通义千问2.5-7B-Instruct:Ollama零基础部署指南

5分钟玩转通义千问2.5-7B-Instruct&#xff1a;Ollama零基础部署指南 1. 引言 在当前大模型快速发展的背景下&#xff0c;如何高效、便捷地将先进语言模型部署到本地环境&#xff0c;成为开发者和AI爱好者关注的核心问题。通义千问2.5-7B-Instruct作为阿里云于2024年9月发布的…

作者头像 李华
网站建设 2026/7/1 21:07:06

MKLINK在游戏开发中的5个实际应用场景

快速体验 打开 InsCode(快马)平台 https://www.inscode.net输入框内输入如下内容&#xff1a; 创建一个游戏开发资源管理工具&#xff0c;利用MKLINK实现以下功能&#xff1a;1. 游戏资源热更新时的符号链接切换 2. 多版本SDK并存管理 3. 大型资源文件的共享访问 4. 开发/测试…

作者头像 李华
网站建设 2026/7/1 13:12:22

AnimeGANv2技术揭秘:8MB模型的压缩技术

AnimeGANv2技术揭秘&#xff1a;8MB模型的压缩技术 1. 引言&#xff1a;轻量级AI如何实现高质量动漫风格迁移 随着深度学习在图像生成领域的快速发展&#xff0c;风格迁移技术已从实验室走向大众应用。AnimeGANv2作为一款专为“照片转动漫”设计的生成对抗网络&#xff08;GA…

作者头像 李华
网站建设 2026/7/8 6:03:36

AI图像风格迁移新标杆:AnimeGANv2实战评测教程

AI图像风格迁移新标杆&#xff1a;AnimeGANv2实战评测教程 1. 引言 随着深度学习技术的不断演进&#xff0c;AI在图像生成与风格迁移领域的表现愈发惊艳。其中&#xff0c;AnimeGANv2 作为轻量级、高效率的照片转二次元动漫模型&#xff0c;凭借其出色的画风还原能力与极低的…

作者头像 李华
网站建设 2026/7/1 13:12:25

AI如何帮你快速生成TIMES NEW ROMAN风格字体设计

快速体验 打开 InsCode(快马)平台 https://www.inscode.net输入框内输入如下内容&#xff1a; 创建一个AI工具&#xff0c;输入任意文字内容&#xff0c;自动生成TIMES NEW ROMAN风格的字体变体设计。要求&#xff1a;1. 分析TIMES NEW ROMAN的笔画特征&#xff08;衬线、字重…

作者头像 李华