添加到通用字典会导致IndexOutOfRangeException

时间:2013-02-26 17:47:45

标签: c# .net concurrency race-condition

我正在使用某个任务中的字典。

逻辑上我已经设置好了我的密钥永远不会发生冲突,但有时当我添加到字典时,我会得到这个例外。

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()

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

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

3 个答案:

答案 0 :(得分:45)

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

  

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

答案 1 :(得分:20)

您的问题很可能是同步问题。当向其添加词典时,有时需要增加底层结构(数组)的大小。如果要从多个线程添加可能导致IndexOutOfRangeException的线程。您需要使用锁等以确保以安全的方式添加。

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

答案 2 :(得分:15)

所以你可能会想到Whatever! it will just break the one time - 但是没有:

重要提示:一旦字典被破坏,它就会被破坏!

有三个小时的销售(直到IIS按计划进行回收),因为为调试目的添加了一个字典,甚至没有被读取。

enter image description here

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

 private Dictionary<string, string> _debugLookup;

 _debugLookup[key] = virtualPath;

这甚至不是一个静态字典 - 它是一个MVC IViewLocationCache,它是一个实例方法。