字典vs并发字典

时间:2018-02-08 18:07:34

标签: c# asp.net dictionary concurrentdictionary

我正在尝试了解何时使用Dictionary vs ConcurrentDictionary,因为我对“词典”所做的更改之一存在问题。

我有这个词典

private static Dictionary<string, Side> _strategySides = null;

在构造函数中,我将一些键和值添加到我创建的词典中,如此

_strategySides.Add("Combination", Side.Combo);
_strategySides.Add("Collar", Side.Collar);

此代码很好,并且已经在所有环境中运行了一段时间。当我添加

_strategySides.Add("Diagonal", Side.Diagonal);

此代码开始破坏,例外“索引超出了数组的范围。”在字典上。然后我进入了ConcurrentDictionary的概念及其用途,我需要在我的案例中选择ConcurrentDictionary而不是我的案例,因为它是一个多线程应用程序。

所以我向你所有的大师提出的问题是,为什么这些天它都没有抛出异常,而是在我向字典添加内容时开始。任何有关这方面的知识将不胜感激。

3 个答案:

答案 0 :(得分:1)

正如您所提到的,您有多线程应用程序。字典不是线程安全的,并且在代码中的某处,当您向其添加项目时,您正在同时阅读字典 - &gt; IndexOutOfboundsException

documentation中提到了这一点:

  

字典可以同时支持多个读者,只要   集合未被修改。即便如此,通过集合进行枚举   本质上不是一个线程安全的过程。在极少数情况下   枚举与写访问争用,集合必须是   在整个枚举期间锁定。允许收集   您必须通过多个线程访问以进行读写   实现自己的同步。有关线程安全的替代方法,请参阅   ConcurrentDictionary。

答案 1 :(得分:1)

查看此问题的答案:c# Dictionary lookup throws "Index was outside the bounds of the array"

似乎在字典上接收此错误特定于线程安全违规。链接的答案提供了两种处理问题的方法,一种是并发字典。

如果我不得不猜测为什么它之前没有发生:你在构造函数中为静态对象添加条目,这意味着只有1个编写器,还没有读者。

你的新条目可能是在构造函数之外添加的?正在尝试进行此写操作时,另一个线程可能正在读取,并且是不允许的。

答案 2 :(得分:1)

Dictionary不是线程安全的,如果你在从多个线程访问时修改它,可能会发生各种奇怪的事情,包括出现“工作”......直到它没有。使用锁保护它,或使用专为多线程使用而设计的数据结构(即ConcurrentDictionary)。

那么为什么它“起作用” - 这很难明确地知道,但我的赌注是要么根本没有看到问题(即内部字典状态已损坏但你没有注意到它由于你的使用模式),或者只是在执行时间上“幸运”(例如,您可能无意中通过调试器“同步”了线程)。

重点是:不管它是什么,你都不能依赖它!即使“错误的东西”似乎“有效”,你也必须做“正确的事”。这就是多线程编程的本质。