在c#中,如何在多线程环境中迭代IEnumerable

Dan*_* Su 6 c# concurrency ienumerable multithreading dictionary

我在这种情况下,有一个大字典,由一个线程以相当高的频率随机更新,还有另一个线程试图将字典的快照保存为历史记录.我目前正在使用这样的东西:

Dictionary<string, object> dict = new Dictionary<string, object>();
var items = dict.Values.ToList();
Run Code Online (Sandbox Code Playgroud)

这在大多数情况下都可以正常工作,除非它偶尔抛出:

System.InvalidOperationException:集合已被修改; 枚举操作可能无法执行.

我理解为什么会发生这种情况,但我不知道我该怎么做才能避免收集修改错误.

迭代此类集合的最佳方法是什么?

我也试过ConcurrentDictionary,但没有运气.为什么?ConcurrentDictionary线程只在项目级别安全吗?

Pau*_*ter 1

根据文档,您应该能够使用GetEnumerator()ConcurrentDictionary 的方法来获取线程安全的迭代器。

从字典返回的枚举器可以安全地与字典的读取和写入同时使用,但它并不代表字典的即时快照。通过枚举器公开的内容可能包含调用 GetEnumerator 后对字典所做的修改。

由于您正在处理并发线程,因此在一致性方面进行一些权衡并不奇怪,但我希望这种方法的阻塞少于其他答案中给出的强力方法。如果您尝试过,这是行不通的:

var items = concurrentDict.Items.ToList();
Run Code Online (Sandbox Code Playgroud)

但它应该适用于

var items = concurrentDict.GetEnumerator();
Run Code Online (Sandbox Code Playgroud)

或者你可以直接引用迭代器:

foreach(var item in concurrentDict)
{
    valueList.Add(item.Value);
}
Run Code Online (Sandbox Code Playgroud)