Ich habe Queues<T>
noch nie zuvor benutzt, also könnte mir etwas offensichtlich fehlen. Ich versuche, ein Queue<EnemyUserControl>
wie folgt (jedes Bild) zu durchlaufen:
Wenn ein Gegner stirbt, löst die gegnerische Benutzerkontrolle ein Ereignis aus, das ich abonniert habe, und das mache ich (der erste Feind in der Warteschlange wird vom Design entfernt):
%Vor% Nach dem Aufruf der Dequeue-Methode erhalte ich jedoch InvalidOperationException
in der foreach
-Schleife. Wenn ich stattdessen Peek
verwende, gibt es keine Fehler, daher muss etwas mit dem Ändern der Warteschlange selbst durchgeführt werden, da die Warteschlange das Objekt entfernt.
Meine erste Vermutung ist, dass es beschwert, dass ich eine Sammlung ändere, die von der Enumerator iteriert wird, aber die Auslagerung wird außerhalb der Schleife durchgeführt?
Irgendwelche Ideen, was könnte dieses Problem verursachen?
Danke
Dies ist ein typisches Verhalten von Enumeratoren. Die meisten Enumeratoren funktionieren nur dann ordnungsgemäß, wenn die zugrunde liegende Auflistung statisch bleibt. Wenn die Auflistung während der Auflistung einer Auflistung geändert wird, wird der nächste Aufruf von MoveNext
, der vom Block foreach
für Sie eingefügt wird, diese Ausnahme generieren.
Die Operation Dequeue
ändert offensichtlich die Sammlung, und genau das verursacht das Problem. Die Problemumgehung besteht darin, jedes Element, das Sie aus der Zielsammlung entfernen möchten, in eine zweite Sammlung hinzuzufügen. Nachdem die Schleife abgeschlossen ist, können Sie die zweite Sammlung durchlaufen und aus dem Ziel entfernen.
Dies könnte jedoch zumindest etwas peinlich sein, da die Operation Dequeue
nur das nächste Element entfernt. Sie müssen möglicherweise zu einem anderen Sammlertyp wechseln, der beliebige Entfernungen ermöglicht.
Wenn Sie bei Queue
bleiben möchten, müssen Sie jedes Element aus der Warteschlange entfernen und die Elemente, die nicht entfernt werden sollen, erneut in die Warteschlange stellen. Sie benötigen weiterhin die zweite Sammlung, um die Elemente zu verfolgen, die beim erneuten Anordnen ausgelassen werden sollen.
Sie können Elemente nicht aus einer Sammlung entfernen, während Sie darüber iterieren.
Die beste Lösung, die ich gefunden habe, besteht darin, eine "Liste & lt; & gt; toDelete" zu verwenden und alles hinzuzufügen, was Sie zu dieser Liste entfernen möchten. Sobald die foreach-Schleife beendet ist, können Sie die Elemente aus der Zielsammlung mithilfe der Referenzen in der toDelete-Liste wie folgt entfernen:
%Vor%Da es sich hier um eine Warteschlange handelt, können Sie einfach die Anzahl der Auszüge in einer Ganzzahl zählen und eine einfache for-Schleife verwenden, um sie später auszuführen (ich habe nicht so viel Erfahrung mit Warteschlangen in dieser Rücksicht).
Es spielt keine Rolle, wo Sie die Sammlung ändern. Wenn eine Auflistung geändert wird, während Sie ihre Mitglieder aufzählen, erhalten Sie eine Ausnahme. Sie können Sperren verwenden und sicherstellen, dass die Auflistung beim Generieren nicht geändert wird, oder wenn Sie .NET 4.0 verwenden, ersetzen Sie Queue
durch ConcurrentQueue
.
Tags und Links .net c# silverlight queue invalidoperationexception