我可以从该字典的枚举循环中删除 ConcurrentDictionary 中的项目吗?
例如:
ConcurrentDictionary<string,Payload> itemCache = GetItems();
foreach(KeyValuePair<string,Payload> kvPair in itemCache)
{
if(TestItemExpiry(kvPair.Value))
{ // Remove expired item.
itemCache.TryRemove(kvPair.Key, out Payload removedItem);
}
}
显然,使用普通的字典
So for example:
ConcurrentDictionary<string,Payload> itemCache = GetItems();
foreach(KeyValuePair<string,Payload> kvPair in itemCache)
{
if(TestItemExpiry(kvPair.Value))
{ // Remove expired item.
itemCache.TryRemove(kvPair.Key, out Payload removedItem);
}
}
Obviously with an ordinary Dictionary<K,V> this will throw an exception, because removing items changes the dictionary's internal state during the life of the enumeration. It's my understanding that this is not the case for a ConcurrentDictionary, as the provided IEnumerable handles internal state changing. Am I understanding this right? Is there a better pattern to use?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
对我来说很奇怪的是,你现在收到了两个似乎证实你不能这样做的答案。我刚刚自己测试了它,它工作得很好,没有抛出任何异常。
下面是我用来测试行为的代码,后面是输出的摘录(当我按下“C”立即清除
foreach
和S
中的字典时之后停止后台线程)。请注意,我对这个 ConcurrentDictionary 施加了相当大的压力:16 个线程计时器,每个计时器大约每 15 毫秒尝试添加一个项目。在我看来,这个类非常强大,如果您在多线程场景中工作,那么值得您关注。
代码
输出(摘录)
另请注意,根据控制台输出,
foreach
循环似乎锁定了尝试向字典添加值的其他线程。 (我可能是错的,但否则我猜你会在“COUNT”行之间看到一堆“添加条目”行。)It's strange to me that you've now received two answers that seem to confirm you can't do this. I just tested it myself and it worked fine without throwing any exception.
Below is the code I used to test the behavior, followed by an excerpt of the output (around when I pressed 'C' to clear the dictionary in a
foreach
andS
immediately afterwards to stop the background threads). Notice that I put a pretty substantial amount of stress on thisConcurrentDictionary
: 16 threading timers each attempting to add an item roughly every 15 milliseconds.It seems to me this class is quite robust, and worth your attention if you're working in a multithreaded scenario.
Code
Output (excerpt)
Also note that, based on the console output, it looks like the
foreach
loop locked out the other threads that were trying to add values to the dictionary. (I could be wrong, but otherwise I would've guessed you would've seen a bunch of "Added entry" lines between the "COUNT" lines.)只是为了确认官方文档明确指出它是安全的:
Just to confirm that the official documentation explicitly states that it is safe:
在检查丹涛解决方案并独立测试后进行编辑。
是的,这是简短的答案。它不会例外,它似乎确实使用了细粒度锁定,并且按照广告宣传的那样工作。
鲍勃.
Edit, after checking Dan Tao solution and testing independently.
Yes, is the short answer. It won't except, it does seem to use fine grained locking, and works as advertised.
Bob.
有关此行为的其他信息可以在此处找到:
MSDN 博客
片段:
Additional information on this behavior can be found here:
MSDN Blog
Snippet: