等待ConcurrentDictionary中所有线程完成写入

3

这里有一个并发字典,它从不同的来源收集信息。每分钟会自动刷新一次数据,并将已经收集到的数据传递给另一个处理程序。

var currentDictionarySnapshot = _currentDictionary;
_currentDictionary = new ConcurrentDictionary<int, string>();
return new ReadOnlyDictionary<int, string>(currentDictionarySnapshot);

我需要做的是使 currentDictionarySnapshot 等待所有引用它的线程完成写操作,并在此之后创建新的 ReadOnlyDictionary。 如果 ConcurrentDictionary 本身支持此功能,那么可以直接使用,否则应该如何实现呢?

1
你可以考虑使用Task.WhenAll(Task1, Task2,...);方法。 - chouaib
我的编写方法不是异步的,即使是异步的,也很难区分主要字典和快照的任务。 - Sovent
2个回答

0
从概念上看,您似乎需要一个ReaderWriterLockSlim。 "读者"将是写入字典的线程。 "作者"是复制字典的线程。
请注意,内置的RWL不具有可扩展性。它们仅在每个操作上在某些数据结构上内部锁定。这破坏了通过锁定分区实现可扩展性的ConcurrentDictionary的可扩展性属性。

-1

好的,我解决问题的方法是创建一个带有ManualResetEventSlim的类,并向其中添加计数器。当需要读取时,我像使用ConcurrentDictionary一样对该类进行快照,并等待计数器变为0。


你如何确保在计数降至零后不会再有其他编写器出现?无论如何,这并不是一个答案,因为它太模糊了。 - usr
我创建快照并用一个新的实例替换了这个类的旧实例。旧实例将与其写入者保持连接,并允许它们完成操作。 - Sovent
通过复制进行快照不是即时的。你会得到一个随着时间“涂抹”的字典。无论如何,这并没有回答问题,即如何等待写入完成。即使你是OP,你的答案也要遵守与其他答案相同的标准。 - usr
这不是通过复制进行快照,而是我创建了字典的另一个引用并从中创建只读字典。然后,我使旧变量引用一个新的空字典,因此所有新写入者都会进入新字典。我无法粘贴整个解决方案代码,因为它受雇主的限制。但我的答案会帮助我解决问题,我认为这才是关键。 - Sovent
创建另一个引用并不能阻止编写器向旧字典中写入。他们仍然可能拥有旧的引用。您需要回答被问到的问题。这并不重要,这是否是您选择的最终方法。 - usr

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接