web-dev-qa-db-fra.com

Ajout à un dictionnaire générique causent indexoutofrangeException

J'utilise un dictionnaire à l'intérieur d'une tâche.

Logiquement, je l'ai mis de côté pour que mes clés ne s'affrontent jamais, bien que parfois, lorsque j'ajoute au dictionnaire, je reçois cette 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()

Je comprends qu'il peut y avoir des problèmes de concurrence d'essayer d'éliminer ou d'ajouter la même clé à plusieurs reprises, mais j'ai comptabilisé cette algorithmique.

Qu'est-ce qui cause l'ajout d'échouer parfois? Quelle est la meilleure façon de travailler autour de cela?

30
Austin Harris

Vous auriez dû avoir regardé la documentation. Que ce qu'il dit:

Un dictionnaire peut prendre en charge plusieurs lecteurs simultanément, tant que la collection n'est pas modifiée. Malgré tout, énumérer à travers une collection n'est intrinsèquement pas une procédure de sécurité. Dans le cas rare où une énumération soutient avec les accès à l'écriture, la collection doit être verrouillée pendant toute la dénombrement. Pour permettre à la collection d'accéder à plusieurs threads pour la lecture et l'écriture, vous devez mettre en œuvre votre propre synchronisation. Pour une alternative à thread-Safe, voir Concurrenttrictionnaire.

47
Dzienny

Votre problème est la synchronisation la plus probable. Lorsqu'un dictionnaire est ajouté à celui-ci doit parfois augmenter la taille de la structure sous-jacente (une matrice). Si vous ajoutez de plusieurs threads pouvant entraîner un IndexOutOfRangeException. Vous devez utiliser des serrures, etc. pour vous assurer que vous ajoutez de manière sûre.

Sinon, vous pouvez utiliser un ConcurrentRentRictionardiction qui est une collection de fil-sécurité.

20
NominSim