添加到通用字典会导致IndexOutOfRangeException

Aus*_*ris 29 .net c# 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()
Run Code Online (Sandbox Code Playgroud)

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

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

Dzi*_*nny 47

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

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

  • 我现在正在使用 ConcurrentDictionary。谢谢! (2认同)

Nom*_*Sim 20

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

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


Sim*_*ver 16

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

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

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

在此输入图像描述

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

 private Dictionary<string, string> _debugLookup;

 _debugLookup[key] = virtualPath;
Run Code Online (Sandbox Code Playgroud)

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

  • 完全一样的事情发生在我身上。在多线程环境中共享一个“ HttpClient”对象。如果您需要添加/删除标题(只是一个字典),它将进入您上面发布的状态。我认为`HttpClient`是线程安全的!是的,不 (2认同)