如果我有一个ConcurrentDictionary,我是否需要在使用它循环时锁定它foreach?
我有一个ConcurrentDictionary对象,我想将其设置为Dictionary对象.
不允许在他们之间施放.那我该怎么做?
我遇到了一个有趣的问题.知道ConcurrentDictionary<TKey, TValue>在被修改时安全可枚举,(在我的情况下)迭代可能消失或多次出现的元素的不必要的副作用,我决定自己创建一个快照,使用ToList().既然ConcurrentDictionary<TKey, TValue>也实现了ICollection<KeyValuePair<TKey, TValue>>,这会导致List(IEnumerable<T> collection)使用它Count,然后使用当前项目在字典的当前大小中创建一个数组,然后尝试复制项目using ICollection<T>.CopyTo(T[] array, int arrayIndex),调用它的ConcurrentDictionary<TKey, TValue>实现,最后抛出一个ArgumentExceptionif元素被添加在此期间到字典.
全部锁定会破坏使用集合的重点,所以我的选择似乎是继续捕获异常并重试(这绝对不是问题的正确答案),或者实现我自己的ToList()专用版本对于这个问题(但是再一次,简单地增加一个列表然后可能将其修剪为适合几个元素的大小似乎是一种过度杀伤,并且使用LinkedList会降低索引性能).
此外,似乎添加某些LINQ方法在后台创建某种缓冲区(例如OrderBy)似乎以性能为代价来修复问题,但裸露ToList()显然没有,并且它不值得"扩充"当不需要其他功能时,使用另一种方法.
这可能是任何并发收集的问题吗?
在创建此类快照时,将性能命中率降至最低的合理解决方法是什么?(最好在一些LINQ魔法结束时.)
编辑:
在调查之后,我可以确认,ToArray()(我认为我昨天刚刚通过它)确实解决了快照问题,只要它只是一个简单的快照,在拍摄快照之前需要额外的功能时它没有帮助(例如过滤,排序),最后还需要一个列表/数组.(在这种情况下,需要额外调用,重新创建新集合.)
我没有指出快照可能需要也可能不需要经过这些修改,所以应该在最后进行,最好是,所以我将这个添加到问题中.
(另外,如果有人对标题有更好的想法,请告诉.)
MSDN声明从字典返回的枚举器不代表字典的时刻快照.虽然在多线程环境中很少需要它,但如果有人想要,获取ConcurrentDictionary的即时快照的最佳方法是什么?