Добавление в общий словарь вызывает IndexOutOfRangeException
Я использую словарь внутри некоторой задачи.
Логически я настроил его так, чтобы мои ключи никогда не столкнулись, хотя иногда, когда я добавляю в словарь, я получаю это исключение.
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()
Я понимаю, что может возникнуть проблема concurrency при попытке удалить или добавить один и тот же ключ несколько раз, но я выполнил это алгоритмически.
Что приводит к сбою добавления?
Каков наилучший способ обойти это?
Ответы
Ответ 1
Вы должны были посмотреть на документацию. Что он говорит:
Словарь может поддерживать несколько считывателей одновременно, пока коллекция не будет изменена. Тем не менее, перечисление через коллекцию по существу не является потокобезопасной процедурой. В редком случае, когда перечисление связано с доступом к записи, сбор должен быть заблокирован во время всего перечисления. Чтобы обеспечить доступ к коллекции несколькими потоками для чтения и записи, вы должны реализовать свою собственную синхронизацию. Для альтернативы, защищенной потоком, см. ConcurrentDictionary.
Ответ 2
Ваша проблема, скорее всего, синхронизация. Когда словарь добавляется к нему, иногда требуется увеличить размер базовой структуры (массива). Если вы добавляете из нескольких потоков, что может привести к IndexOutOfRangeException
. Вам нужно использовать блокировки и т.д., Чтобы убедиться, что вы добавляете их безопасным способом.
В качестве альтернативы вы можете использовать ConcurrentDictionary, который представляет собой потокобезопасную коллекцию.
Ответ 3
Итак, вы можете подумать Whatever! it will just break the one time
- но nope:
Важно: как только словарь сломан, он сломан!
Прошло три часа продаж (до тех пор, пока IIS не переработал по расписанию) из-за того, что словарь добавлен для целей отладки, о которых даже не читали.
![введите описание изображения здесь]()
Примечание. Это выполнялось в течение 3,5 лет, прежде чем я попал в это состояние.
private Dictionary<string, string> _debugLookup;
_debugLookup[key] = virtualPath;
Это не был даже статический словарь - это был метод экземпляра MVC IViewLocationCache
.