IndexOutOfRangeException при добавлении в Hashset‹T›

У меня есть простое приложение, которое добавляет около 7 миллионов коротких строк в HashSet<string>. Иногда я получаю исключение во время вызова Hashset.Add(): System.Collections.Generic.HashSet`1.IncreaseCapacity(): Индекс был за пределами массива.

Это периодически возникающая проблема, которая, похоже, связана с памятью, но это на сервере win2k8 R2 с 16 ГБ, больше ничего не происходит, большая часть этой физической памяти доступна. Любые идеи?


person dcrobbins    schedule 29.11.2010    source источник
comment
вы добавляете многопоточность?   -  person herzmeister    schedule 29.11.2010
comment
Я только что создал проект, который добавляет int.MaxValue Guids на 4-ядерный ПК с использованием распараллеливания, и он не дает сбоев.   -  person Yuriy Faktorovich    schedule 29.11.2010
comment
да, это была проблема. Я должен был знать. Спасибо Герцмайстер   -  person dcrobbins    schedule 29.11.2010
comment
@herz - это был ответ, возможно, вы захотите опубликовать его.   -  person Hans Passant    schedule 29.11.2010


Ответы (2)


HashSet<T> не является потокобезопасным. Особенно при добавлении элементов в многопоточном сценарии и необходимости увеличения внутренней емкости все может выйти из строя.

person herzmeister    schedule 29.11.2010
comment
+1 IndexOutOfRangeException — это определенный индикатор того, что существуют проблемы с потоками во время выполнения, когда он выдается из операции добавления в коллекции. - person Tim Lloyd; 29.11.2010
comment
Спасибо, это очень помогает. Мой проект использовал Dictionary<key, bool>, и никаких проблем не было обнаружено, пока я не изменил его на HashSet и не было выдано какое-то внешнее исключение. Не уверен, почему это не потерпело неудачу раньше, потому что Dictionary также не является потокобезопасным - person phuclv; 18.06.2019

Методы экземпляра HashSet<T> не являются потокобезопасными. В частности, когда вы пытаетесь добавить элемент, из-за которого набор выходит за границы существующего массива более чем в одном потоке за раз, переменные экземпляра, используемые для отслеживания размера набора и последнего индекса в набор можно обновлять в обоих потоках. В частности, если последнее значение индекса обновляется вторым потоком (с большим значением) до того, как первый поток завершит копирование целевого массива, он может попытаться получить доступ к элементу локального массива, который не существует, поскольку локальный массив был выделен для хранения только половины того количества элементов, которое было выделено вторым потоком.

person tvanfosson    schedule 29.11.2010