33

我在一些任务中使用字典。

从逻辑上讲,我已经设置了它,以便我的键永远不会发生冲突,但有时当我添加到字典时,我会得到这个异常。

Index was outside the bounds of the array.
at System.Collections.Generic.Dictionary`2.Insert(TKey key, TValue value, Boolean add)
   at System.Collections.Generic.Dictionary`2.Add(TKey key, TValue value)
   at Rpc.<MapIntoRpc>b__4[T](Object x) in Rpc.cs:line 113
   at System.Threading.Tasks.Task`1.InvokeFuture(Object futureAsObj)
   at System.Threading.Tasks.Task.InnerInvoke()
   at System.Threading.Tasks.Task.Execute()

我知道尝试多次删除或添加相同的密钥可能会出现并发问题,但我已经在算法上考虑了这一点。

是什么导致添加有时失败?解决这个问题的最佳方法是什么?

4

3 回答 3

54

您应该查看文档。这就是它所说的:

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

于 2013-02-26T17:58:29.173 回答
23

您的问题很可能是同步。添加 Dictionary 时,有时需要增加底层结构(数组)的大小。如果您从可能导致IndexOutOfRangeException. 您需要使用锁等来确保以安全的方式添加。

或者,您可以使用ConcurrentDictionary它是一个线程安全的集合。

于 2013-02-26T18:00:43.997 回答
16

所以你可能会想Whatever! it will just break the one time——但不是:

重要提示:一旦字典坏了,它就坏了!

由于添加了用于调试目的的字典,甚至从未被读取过,因此销售了三个小时(直到 IIS 按计划回收)。

在此处输入图像描述

注意:在我遇到这种情况之前,它已经运行了 3.5 年。

 private Dictionary<string, string> _debugLookup;

 _debugLookup[key] = virtualPath;

这甚至不是一个静态字典——它是一个IViewLocationCache作为实例方法的 MVC。

于 2016-10-01T18:00:44.263 回答