Système.InvalidOperationException: Collection a été modifiée
Je suis une exception suivante lors de l'énumération par une file d'attente:
Système.InvalidOperationException:
La Collection a été modifiée; l'énumération
l'opération ne peut pas exécuter
voici l'extrait de code:
1: private bool extractWriteActions(out List<WriteChannel> channelWrites)
2: {
3: channelWrites = new List<WriteChannel>();
4: foreach (TpotAction action in tpotActionQueue)
5: {
6: if (action is WriteChannel)
7: {
8: channelWrites.Add((WriteChannel)action);
9: lock(tpotActionQueue)
10: {
11: action.Status = RecordStatus.Batched;
12: }
13: }
14: }
15: return (channelWrites.Count > 0);
16: }
Je crois que je comprends le problème d'altération de la table de hachage à action.Status = RecordStatus.Batched
, qui vis jusqu'à la MoveNext() sur l'énumérateur.
La Question est, comment puis-je la mettre en "modèle" correctement?
- Pourquoi êtes-vous de verrouillage de la file d'attente? Ce code ne fait pas de sens pour moi.
- Le plus grand point de l'agent recenseur de la documentation est-ce que "L'agent recenseur n'a pas accès exclusif à la collection; par conséquent, l'énumération d'une collection n'est pas intrinsèquement une procédure thread-safe. Pour garantir la sécurité des threads au cours de l'énumération, vous pouvez verrouiller la collection au cours de l'ensemble de l'énumération. Pour permettre la collecte pour être accessible par plusieurs threads pour la lecture et l'écriture, vous devez mettre en place votre propre synchronisation".
- La droite. Ce code ne fait rien, même vaguement, comme ça.
- Envisager l'utilisation d'un lecteur / enregistreur de verrouillage si vous avez besoin de synchroniser des lecteurs et des auteurs sur plusieurs threads.
Vous devez vous connecter pour publier un commentaire.
Vous êtes autorisé à changer la valeur d'un élément dans une collection. L'erreur que vous obtenez signifie qu'un article a été ajouté ou retiré à savoir: la collection elle-même a été modifié, et non un élément à l'intérieur de la collection. Ceci est probablement causé par un autre thread ajouter ou supprimer des éléments de cette collection.
Vous devez verrouiller votre file d'attente au début de votre méthode, pour éviter que d'autres Threads modifiant la collection, tandis que vous y accédez. Ou vous pouvez verrouiller la collection avant même l'appel de cette méthode.
Je pense que j'ai eu une exception similaire lors de l'utilisation d'un
foreach
boucle sur une Collection où j'ai essayé de supprimer des éléments de la Collection (ou il peut avoir été une Liste, je ne me souviens pas). J'ai fini par trouver autour d'elle à l'aide d'unfor
boucle. Essayez peut-être de quelque chose comme ce qui suit:Vous n'avez pas de définition pour
tpotActionQueue
, mais si c'est juste normalList<TpotAction>
alors que la ligne n'est pas votre problème. Modification de la collecte est de l'ajout ou de la suppression de membres - pas de définition d'une propriété sur un objet contenu.Vous avez un
lock(tpotActionQueue)
et une balise de fil de sécurité, si ma conjecture est qu'il y a un autre thread de l'ajout ou de la suppression d'éléments detpotActionQueue
alors que vous êtes de l'énumération. Vous avez probablement besoin de synchroniser ces accès.Je pense que tout ce que vous devez faire est de cesser d'utiliser le foreach et, au lieu de basculer d'une boucle for
Ce Qui Concerne, Mike.
Comment quelques-uns LINQy bonté?
Je pense que vous devez avoir un autre thread modifiant la tpotActionQueue alors que vous êtes une itération sur elle. Puisque vous êtes seulement de verrouillage que la file d'attente à l'intérieur de la boucle for, c'est possible.