Подтвердить что ты не робот

Добавление в общий словарь вызывает 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 при попытке удалить или добавить один и тот же ключ несколько раз, но я выполнил это алгоритмически.

Что приводит к сбою добавления? Каков наилучший способ обойти это?

4b9b3361

Ответ 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.