C# 从 ConcurrentDictionary 中取出并移除第一个元素

C# 从 ConcurrentDictionary 中取出并移除第一个元素

要从 ConcurrentDictionary<byte, int> 中取出并移除第一个元素,需要结合 遍历原子移除操作 。由于 ConcurrentDictionary 是无序集合,"第一个元素" 通常是指最早添加的元素(按插入顺序)。

以下是几种实现方法:

方法 1:使用 TryRemove 结合 FirstOrDefault

cs 复制代码
// 获取第一个键值对(如果存在)
var firstPair = WorkerHandleMsg_Up.DI_TaskID.FirstOrDefault();

if (firstPair.Key != default(byte)) // 检查是否有元素
{
    // 尝试原子性地移除该元素(可能已被其他线程移除)
    if (WorkerHandleMsg_Up.DI_TaskID.TryRemove(firstPair.Key, out int removedValue))
    {
        Console.WriteLine($"成功移除第一个元素: Key={firstPair.Key}, Value={removedValue}");
    }
    else
    {
        Console.WriteLine("元素已被其他线程移除");
    }
}
else
{
    Console.WriteLine("字典为空");
}

方法 2:使用 Keys 集合(更简洁)

cs 复制代码
if (WorkerHandleMsg_Up.DI_TaskID.Count > 0)
{
    // 获取第一个键(可能已被其他线程移除)
    byte firstKey = WorkerHandleMsg_Up.DI_TaskID.Keys.First();
    
    // 原子性地尝试移除该键
    if (WorkerHandleMsg_Up.DI_TaskID.TryRemove(firstKey, out int removedValue))
    {
        Console.WriteLine($"成功移除: Key={firstKey}, Value={removedValue}");
    }
    else
    {
        Console.WriteLine("元素已被其他线程移除");
    }
}
else
{
    Console.WriteLine("字典为空");
}

方法 3:循环尝试(高并发场景更可靠)

cs 复制代码
bool removed = false;
while (!removed && WorkerHandleMsg_Up.DI_TaskID.Count > 0)
{
    byte firstKey = WorkerHandleMsg_Up.DI_TaskID.Keys.First();
    removed = WorkerHandleMsg_Up.DI_TaskID.TryRemove(firstKey, out int removedValue);
    
    if (removed)
    {
        Console.WriteLine($"成功移除: Key={firstKey}, Value={removedValue}");
    }
    // 否则继续尝试,直到成功或字典为空
}

if (!removed)
{
    Console.WriteLine("字典为空或所有元素已被其他线程移除");
}

注意事项

1)线程安全

  • ConcurrentDictionary 的所有操作都是线程安全的
  • 上述代码在多线程环境下能正确工作,但不保证获取到的总是 "第一个" 元素(取决于并发操作)

2)顺序问题

  • ConcurrentDictionary 不保证元素顺序,"第一个元素" 通常是指最早添加的元素
  • 如果需要严格的顺序,请使用 ConcurrentQueueConcurrentBag

3)性能考虑

  • 方法 3 的循环尝试在极端高并发下可能影响性能,但更可靠
  • 大多数场景下,方法 1 或 2 已足够

扩展:如果需要有序集合

如果确实需要按插入顺序处理元素,建议改用 ConcurrentQueue<KeyValuePair<byte, int>>

cs 复制代码
// 声明时使用 ConcurrentQueue 代替 ConcurrentDictionary
private readonly ConcurrentQueue<KeyValuePair<byte, int>> DI_TaskID = new();

// 添加元素
DI_TaskID.Enqueue(new KeyValuePair<byte, int>(di, taskId));

// 取出并移除第一个元素(按插入顺序)
if (DI_TaskID.TryDequeue(out var firstElement))
{
    byte key = firstElement.Key;
    int value = firstElement.Value;
    Console.WriteLine($"移除第一个元素: Key={key}, Value={value}");
}
相关推荐
硅的褶皱1 小时前
对比分析LinkedBlockingQueue和SynchronousQueue
java·并发编程
MoFe11 小时前
【.net core】天地图坐标转换为高德地图坐标(WGS84 坐标转 GCJ02 坐标)
java·前端·.netcore
季鸢2 小时前
Java设计模式之观察者模式详解
java·观察者模式·设计模式
Fanxt_Ja2 小时前
【JVM】三色标记法原理
java·开发语言·jvm·算法
蓝婷儿2 小时前
6个月Python学习计划 Day 15 - 函数式编程、高阶函数、生成器/迭代器
开发语言·python·学习
绿荫阿广2 小时前
互联网不景气了那就玩玩嵌入式吧,用纯.NET开发并制作一个智能桌面机器人(五):使用.NET为树莓派开发Wifi配网功能
c#·.net
love530love2 小时前
【笔记】在 MSYS2(MINGW64)中正确安装 Rust
运维·开发语言·人工智能·windows·笔记·python·rust
Mr Aokey2 小时前
Spring MVC参数绑定终极手册:单&多参/对象/集合/JSON/文件上传精讲
java·后端·spring
slandarer3 小时前
MATLAB | 绘图复刻(十九)| 轻松拿捏 Nature Communications 绘图
开发语言·matlab
狐凄3 小时前
Python实例题:Python计算二元二次方程组
开发语言·python