ConcurrentQueue入队后无法出队:单例Repository哈希码不一致问题
问题分析与解决方案
问题根源
哈希码不一致直接说明:你在AddItem方法和循环处理逻辑中操作的是两个完全不同的ConcurrentQueue<Order>实例。本质原因是你的Repository单例模式实现错误,导致系统中存在多个Repository实例,每个实例都维护了自己独立的队列——接口调用的是A实例的队列,循环处理的是B实例的队列,自然拿不到数据。
排查与修复步骤
检查单例实现的核心错误点
- 确认
Repository的构造函数是否为private:如果构造函数是公共的,外部代码可以随意new出新的实例,直接破坏单例 - 检查单例属性的getter逻辑:比如是否在
get里错误地每次都返回new Repository(),或者懒加载的双重检查锁写错了,导致每次获取实例都创建新对象 - 若使用了依赖注入(比如ServiceStack的IOC容器):确认是否把
Repository注册为单例,而非每次请求都创建新实例
- 确认
修复单例实现(示例)
下面是一个标准的饿汉式单例实现,避免多线程下的实例重复创建问题:public class Repository { // 静态只读实例,类加载时初始化,保证唯一 private static readonly Repository _instance = new Repository(); // 队列实例与单例绑定,确保全局唯一 private readonly ConcurrentQueue<Order> _orderQueue = new ConcurrentQueue<Order>(); // 私有构造函数,禁止外部实例化 private Repository() {} // 全局访问入口 public static Repository Instance => _instance; public void AddItem(Order order) { _orderQueue.Enqueue(order); // 可添加日志验证:Console.WriteLine($"AddItem 队列哈希: {_orderQueue.GetHashCode()}"); } public void CreateOrder() { while (true) { // 可添加日志验证:Console.WriteLine($"处理循环 队列哈希: {_orderQueue.GetHashCode()}"); if (_orderQueue.TryDequeue(out var order)) { // 执行订单处理逻辑 } // 空转时休眠,降低CPU占用 Thread.Sleep(100); } } }统一实例获取方式
- Service类中必须通过
Repository.Instance调用AddItem,禁止自行new Repository() - 应用启动时的线程,同样通过
Repository.Instance调用CreateOrder方法
- Service类中必须通过
验证修复效果
在AddItem和CreateOrder方法中分别输出队列的哈希码,确认两次输出的哈希码完全一致,说明操作的是同一个队列实例。
额外注意事项
- 如果使用ServiceStack的依赖注入,需在容器中注册单例:
确保Service类通过构造函数注入的container.RegisterAs<Repository, IRepository>(ReuseScope.Singleton);IRepository是全局唯一实例 - 后台线程处理订单时,若需要更新UI,必须通过WinForms的
Control.Invoke/Control.BeginInvoke切换到UI线程操作,避免跨线程异常
内容的提问来源于stack exchange,提问作者Saghar Francis
相关产品推荐
相关产品推荐

