ThinkGeo.com    |     Documentation    |     Premium Support

Collection Modified Errors

If I make several edits to layers concurrently without enough time for the previousoperation to complete, for instance removing layers one by one or move a layer up in the drawing order several times before the draw for the first action has completed, I receive a Collection modified error. Is there a way to avoid this?



Nelson, 
  
 A common way to avoid the cross threading issue is by using lock (SyncLock in VB.NET). For example, whenever you are going to do some operations on the collections, just lock one object. And whenever you are going to draw the map, lock the same object. In this way, the collection operation (remove a layer or move a layer up) will not be start until the drawing is finished, and vice verse.  
  
 To lock one object while drawing, you can simply create a new FeatureLayer, override the DrawCore method and check the lock root for it. Pass in the object you want to lock to LockRoot and it will work.   
  
 
Class LockedFeatureLayer 
   Inherits FeatureLayer 
Private _LockRoot As Object 
   Public Property LockRoot() As Object 
       Get 
           Return _LockRoot 
       End Get 
       Set(ByVal value As Object) 
           _LockRoot = value 
       End Set 
   End Property 
   
   Protected Overloads Overrides Sub DrawCore(ByVal canvas As GeoCanvas, ByVal labelsInAllLayers As Collection(Of SimpleCandidate)) 
       SyncLock LockRoot 
           MyBase.DrawCore(canvas, labelsInAllLayers) 
       End SyncLock 
   End Sub 
End Class 
 
 Finally, just remind you usually want to inherit from a concrete FeatureLayer like ShapeFileFeatureLayer or PostgreFeatureLayer, the code above is just showing the idea. 
  
 Thanks, 
  
 Ben

Ok I'll look into this. I realize Map Suite utilizes multi-threading so I'm assuming that is why you are suggesting this work aroudn but I just wanted to clarify that you didn't think I was necessarily utilizing multi-threading in my application and that may be why I was getting the above error, because I'm not.


Thanks for the suggestion.



Nelson, 
  
 In fact, the current Desktop Edition 3.0.199 doesn’t have the MutliThreading turned on by default (because it has some cross threading issue) and I thought you are of course using the multi-threading yourself which leads to the problem. Seems I’m wrong then. So now can you let me know how to recreate this issue with single thread? As you mentioned “make several edits to layers concurrently” and “move a layer up  … before the draw  … has completed”, just not very sure what does that exactly mean with single thread, can you provide a piece of code for that? 
  
 Thanks, 
  
 Ben

Sorry, I should have been more clear. I have a tree view listing the layers loaded in the map with an add and delete button. If i go one by one and delete the layers quickly, the map still seems to be in the process of disposing data and what not and gives me a collection modified error. It does not point to a line in code where it takes place. 
  
 {"Collection was modified; enumeration operation may not execute."} 
 Data: {System.Collections.ListDictionaryInternal} 


Sorry, I should have been more clear. I have a tree view listing the layers loaded in the map with an add and delete button. If i go one by one and delete the layers quickly, the map still seems to be in the process of disposing data and what not and gives me a collection modified error. It does not point to a line in code where it takes place. 
  
 {"Collection was modified; enumeration operation may not execute."} 
 Data: {System.Collections.ListDictionaryInternal} 


Nelson, 
  
 I guess after removing a node in the tree view,  you remove the corresponding layer and redraw the map. Just wondering did the application get “No Response” before the map finished drawing? If only use Single Thread, I think the application will stun here and will only be available after drawing is completed. 
  
 If you are using one thread for the UI and the other thread for the other parts,  you can try the “lock” statements above, which may solve the problem.  
  
 Thanks, 
  
 Ben

Yes, I am removing the layers from a TreeView which in that same routine removes the layer from the map. Actually, two maps; A locus map and the main map.  
  
 I am not building multi-threading into the application nor have I manually turned on multi-threading on the map control. I do not get a No Response. If the map is ever not finished drawing, I can continue to pan and zoom just fine. This is why I thought maybe there was some slight multi-threading in use in the component. 
  
 But as I mentioned earlier, if I add layers rapidly through a dialog box or remove them rapidly through the tree view or button then this type of error occurs. 





 


Nelson, 


It's strange that in our test, the app had no response before finished drawing. Could you please send a simple demo for us to recreate? Here is our test sample, please let me know what's the difference between yours.


Thanks,


Ben 




574-Demo.zip (10.1 KB)

With the new assemblies sent via email, the behavior you describe is true. I have incorporated some of the new features into my viewer now so I can't or would like not to roll back to verify.


In this way it is evident it is running in a single thread mode and no error occurs. Indeed, the window does hang as the operation completes.


Thank you.



Nelson, 
  
 That’s fine. Let’s refocus on that when you encountered it again. 
  
 Thanks, 
  
 Ben.