File d'attente de boucle ForEach jeter InvalidOperationException
Je n'ai pas utilisé Queues<T>
pour tout réel degré avant, donc j'ai peut-être raté quelque chose d'évident. Je suis en train de parcourir un Queue<EnemyUserControl>
comme ceci (toutes les images):
foreach (var e in qEnemy)
{
//enemy AI code
}
Quand un ennemi meurt, l'ennemi de contrôle de l'utilisateur soulève un événement que j'ai souscrit et je le fais (le premier ennemi dans la file d'attente est supprimé par la conception):
void Enemy_Killed(object sender, EventArgs e)
{
qEnemy.Dequeue();
//Added TrimExcess to check if the error was caused by NULL values in the Queue (it wasn't :))
qEnemy.TrimExcess();
}
Cependant, après la Résorption de la méthode est appelée, je reçois un InvalidOperationException
sur le foreach
boucle. Lorsque j'utilise Peek
au lieu de cela, il n'y a pas d'erreurs, donc il a de faire quelque chose avec l'évolution de la File d'attente depuis la file d'attente supprime l'objet.
Ma première hypothèse est que c'est de se plaindre que je suis à la modification d'une collection qui est itérée par l'agent Recenseur, mais la file d'attente est effectuée en dehors de la boucle?
Les idées de ce que pourrait être l'origine de ce problème?
Grâce
while(queue.Any()) queue.Dequeue();
OriginalL'auteur keyboardP | 2011-06-04
Vous devez vous connecter pour publier un commentaire.
Vous êtes en train de modifier la file d'attente à l'intérieur de
foreach
boucle. C'est ce qui fait l'exception.Simplifié le code pour illustrer le problème:
Solution Possible est d'ajouter
ToList()
, comme ceci:Movement
méthode qui, à son tour, soulève les tués de l'événement (je pensais que c'était soulevée par certains de code en dehors de la boucle), de sorte que la file d'attente est effectuée à l'intérieur de la boucle. LeToList()
méthode fonctionne parfaitement. Merci!OriginalL'auteur Alex Aza
Je sais que c'est un vieux post, mais ce sur les éléments suivants :
Acclamations
Une autre grande réponse! Venez de modifier, en accord avec @DaveD préoccupation de l'
OriginalL'auteur DarkUrse
C'est un comportement typique des agents recenseurs. La plupart des agents recenseurs sont conçues pour fonctionner correctement que si la collection sous-jacente reste statique. Si la collection est modifié alors que l'énumération d'une collecte alors le prochain appel à
MoveNext
, qui est injecté pour vous par leforeach
bloc, va générer cette exception.La
Dequeue
fonctionnement de toute évidence des modifications de la collection et c'est ce qui est à l'origine du problème. La solution de contournement consiste à ajouter chaque élément que vous souhaitez supprimer de la collection cible dans un deuxième collection. Après la boucle est terminée, vous pouvez ensuite parcourir la deuxième collecte et de supprimer à partir de la cible.Cependant, cela peut être un peu maladroit, à tout le moins, depuis le
Dequeue
opération supprime uniquement l'élément suivant. Vous pourriez avoir à passer à un autre type de collection qui permet à l'arbitraire du déménagement.Si vous voulez coller avec un
Queue
ensuite, vous serez forcé de retirer chaque article, et à condition de re-file d'attente de ces éléments qui ne doivent pas être enlevés. Vous aurez toujours besoin de la deuxième collection de garder une trace des éléments qui sont d'accord de supprimer, dans la re-mise en queue.OriginalL'auteur Brian Gideon
Vieux post, mais pensé que je voudrais offrir une meilleure réponse:
Comme DarkUrse la réponse pourrait provoquer une exception si la file d'attente est vide
OriginalL'auteur JohnChris
Vous ne pouvez pas supprimer des éléments d'une collection tout en évoluant au-dessus d'eux.
La meilleure solution que j'ai trouvé est d'utiliser une "Liste<> toDelete" et ajouter ce que vous voulez supprimer de la liste. Une fois la boucle foreach se termine, vous pouvez supprimer les éléments de la collection cible à l'aide des références dans le toDelete liste comme suit:
Maintenant, puisque c'est une File d'attente, vous pourriez tout simplement être en mesure de compter le nombre de fois que vous souhaitez Retirer un entier et d'utiliser une simple boucle for de les exécuter plus tard (je n'ai pas beaucoup d'expérience avec les files d'attente à cet égard).
OriginalL'auteur June Rhodes
Il n'a pas d'importance où vous êtes en train de modifier la collection. Si une collection est modifiée alors que vous êtes à l'énumération de ses membres, vous bénéficiez d'exception. Vous pouvez utiliser des verrous et assurez-vous que la collection n'est pas modifiée lorsque iterrating ou si vous êtes en utilisant .NET 4.0 remplacer
Queue
avecConcurrentQueue
.OriginalL'auteur Xaqron