Die Sammlung wurde geändert, die Aufzählungsoperation wird möglicherweise nicht ausgeführt

8

Ich habe Multithread-Anwendung und ich bekomme diesen Fehler

%Vor%

Ich habe wahrscheinlich Probleme mit meiner Sammlung, weil ich in einem Thread meine Sammlung lese und in einem anderen Thread die Sammlung ändere.

%Vor%

Ich versuche, die Sammlung mit diesem Code zu sperren, funktioniert aber nicht.

%Vor%

Irgendwelche Ideen, um dieses Problem zu beheben?

    
PATO7 29.03.2012, 12:14
quelle

5 Antworten

8

Dies ist ein ziemlich verbreiteter Fehler - wenn Sie eine Sammlung ändern, während Sie sie mit foreach iterieren, denken Sie daran, dass foreach readonly IEnumerator instance verwendet.

Probieren Sie Schleife durch die Sammlung mit for() mit extra Index überprüfen, so wenn Index ist außerhalb des Bereichs - Sie könnten zusätzliche Logik anwenden, um dies zu behandeln, auch als Schleife Exit-Bedingung können Sie verwenden LINQ Count() , die würde Bewerten Sie den Zählwert jedes Mal, wenn die zugrunde liegende Enumeration ICollection nicht implementiert:

Wenn Markers implementiert IColletion - Sperre auf SyncRoot:

%Vor%

Verwenden Sie for() :

%Vor%

Findet diesen Beitrag möglicherweise nützlich: Wie funktionieren foreach-Schleifen in C #?

    
sll 29.03.2012 12:17
quelle
4

Sie müssen sowohl die Lese- als auch die Schreibseite sperren. Andernfalls wird einer der Threads nicht über die Sperre informiert und versucht, die Sammlung zu lesen / ändern, während der andere die Lese- / Lesefunktion (bzw.) bei gehaltener Sperre ändert

    
Attila 29.03.2012 12:16
quelle
4

Versuchen Sie, einen Klon Ihrer Sammlung zu lesen

%Vor%

Dies erstellt eine neue Kopie Ihrer Sammlung, die nicht von einem anderen Thread betroffen ist, aber im Falle einer umfangreichen Sammlung zu einem Leistungsproblem führen kann.

Ich denke, es ist besser, wenn Sie die Sammlung während des Lese- und Schreibvorgangs sperren.

    
Amir Ismail 29.03.2012 12:17
quelle
0

Sie können eine Foreach verwenden, aber Sie müssen die Sammlung in eine Liste umwandeln und den Punktoperator verwenden, um auf die Verhaltensmethoden zuzugreifen.

Beispiel: Markers.Tolist (). ForEach (i = & gt; i.DeleteObject ())

Nicht ganz sicher, was Sie mit Ihrer Sammlung machen. In meinem Beispiel gehen wir davon aus, dass Sie nur alle Elemente aus der Sammlung löschen möchten, sie können jedoch auf jedes Verhalten angewendet werden, das Sie mit Ihrer Sammlung durchführen möchten.

    
Tim James 18.10.2017 19:36
quelle
0

Ich würde vorschlagen, AsyncCommand zu verwenden, weil AsyncCommand entweder verwendet wird oder nicht, während lock(Markers) die Reentrancy erlaubt. (Siehe Ссылка ):

%Vor%

Mit AsyncLock können Sie auch Thread.Sleep durch seine asynchrone Entsprechung await Task.Delay(TimeSpan.FromSeconds(1))

ersetzen     
Roger 15.11.2017 23:46
quelle

Tags und Links