Adding to a generic dictionary causes IndexOutOfRangeException

♀尐吖头ヾ 提交于 2020-06-09 10:59:20

问题


I'm using a dictionary inside of some Task.

Logically I have set it up so that my Keys will never clash, though sometimes when I am adding to the dictionary I get this Exception.

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

I understand there can be concurrency issues from trying to remove or add the same Key multiple times, but I have accounted for that algorithmically.

What causes the add to sometimes fail? What is the best way to work around that?


回答1:


You should have looked to the documentation. That what it says:

A Dictionary can support multiple readers concurrently, as long as the collection is not modified. Even so, enumerating through a collection is intrinsically not a thread-safe procedure. In the rare case where an enumeration contends with write accesses, the collection must be locked during the entire enumeration. To allow the collection to be accessed by multiple threads for reading and writing, you must implement your own synchronization. For a thread-safe alternative, see ConcurrentDictionary.




回答2:


Your issue is most likely synchronization. When a Dictionary is added to it sometimes needs to increase the size of the underlying structure (an array). If you are adding from multiple threads that may result in an IndexOutOfRangeException. You need to use locks etc. to make sure you are adding in a safe way.

Alternatively you can use a ConcurrentDictionary which is a thread-safe collection.




回答3:


So you might think Whatever! it will just break the one time - but nope:

Important: Once the dictionary is broken it is broken!

There goes three hours of sales (until IIS recycled on a schedule) because of a dictionary added for debugging purposes that wasn't ever even being read from.

Note: This was running for 3.5 years before I hit this condition.

 private Dictionary<string, string> _debugLookup;

 _debugLookup[key] = virtualPath;

This wasn't even a static dictionary - it was an MVC IViewLocationCache that was an instance method.



来源:https://stackoverflow.com/questions/15095817/adding-to-a-generic-dictionary-causes-indexoutofrangeexception

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!