You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

ImmutableDictionary仍抛Collection was modified异常的原因与解决方法

问题根源

你把Dictionary换成ImmutableDictionary后仍然报错,核心原因是:ImmutableDictionary的不可变性只保护字典的键值对结构(不能增删改键值对),但它存储的Value是List<int>——这是个可变集合,其他线程依然可以修改这个List的内容。

当string.Join(",", status.Value)执行时,内部会创建List<int>的枚举器来遍历元素,如果此时其他线程对这个List做了Add/Remove/Clear等修改操作,就会触发"集合已被修改;枚举操作可能无法执行"的异常。

解决方案

给你三个可行的解决思路,按推荐优先级排序:

1. 将Value替换为不可变集合(最优)

把字典里的List<int>换成ImmutableList<int>,让Value本身也具备不可变性,彻底杜绝被修改的可能:

  • 修改函数参数类型:
    public string FormatLoDestStatus(ImmutableDictionary<string, ImmutableList<int>> loDestStatus)
    
  • 构建loDestStatus字典时,把每个List<int>转换成ImmutableList<int>:
    // 示例:原List<int>转ImmutableList<int>
    var immutableList = originalList.ToImmutableList();
    

这样字典的键值对和内部的Value都不可变,多线程访问时不会出现枚举冲突。

2. 对可变List创建快照(快速修复)

如果暂时无法修改字典的Value类型,可以在枚举前先复制一份List的快照,基于快照进行操作:

foreach (var status in loDestStatus)
{
    // 先复制一份快照,避免原List被修改影响枚举
    var valueSnapshot = status.Value.ToList();
    string value = string.Join(",", valueSnapshot).TrimEnd();
    // 后续逻辑不变...
}

这样即使其他线程修改了原List,快照是独立的副本,枚举时不会触发异常。

3. 加锁保护List的访问(最后选择)

如果既不能换不可变集合,又不想做快照,可以对所有访问该List的地方(包括读取和修改)加锁:

  • 首先定义一个与List绑定的锁对象(注意:锁对象要和List一一对应,或者用字典级别的锁,根据实际情况选择)
  • 在读取枚举List时加锁,修改List时也加同一个锁:
// 假设每个List有对应的锁,或者用全局锁(全局锁粒度大,性能差)
lock (status.ValueLock) // 这里需要你提前为每个List创建对应的锁对象
{
    string value = string.Join(",", status.Value).TrimEnd();
}

这种方式要注意锁的粒度,避免出现死锁或性能瓶颈,必须保证所有读写操作都经过同一把锁。

内容的提问来源于stack exchange,提问作者user27330175

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.18 07:33:29