Threadsafe foreach enumeration of lists

后端 未结 11 1599

I need to enumerate though generic IList<> of objects. The contents of the list may change, as in being added or removed by other threads, and this will kill my enumerati

相关标签:
11条回答
  • 2020-12-17 19:23

    This is something that I've recently had to deal with and to me it really depends on what you're doing with the list.

    If you need to use the list at a point in time (given the number of elements currently in it) AND another thread can only ADD to the end of the list, then maybe you just switch out to a FOR loop with a counter. At the point you grab the counter, you're only seeing X numbers of elements in the list. You can walk through the list (while others are adding to the end of it) . . . should not cause a problem.

    Now, if the list needs to have items taken OUT of it by other threads, or CLEARED by other threads, then you'll need to implement one of the locking mechanisms mentioned above. Also, you may want to look at some of the newer "concurrent" collection classes (though I don't believe they implement IList - so you may need refactor for a dictionary).

    0 讨论(0)
  • 2020-12-17 19:24
    ICollection MyCollection;
    // Instantiate and populate the collection
    lock(MyCollection.SyncRoot) {
      // Some operation on the collection, which is now thread safe.
    }
    

    From MSDN

    0 讨论(0)
  • 2020-12-17 19:24

    I recently spend some time multip-threading a large application and had a lot of issues with the foreach operating on list of objects shared across threads.

    In many cases you can use the good old for-loop and immediately assign the object to a copy to use inside the loop. Just keep in mind that all threads writing to the objects of your list should write to different data of the objects. Otherwise, use a lock or a copy as the other contributors suggest.

    Example:

    foreach(var p in Points)
    {
        // work with p...
    }
    

    Can be replaced by:

    for(int i = 0; i < Points.Count; i ++)
    {
       Point p = Points[i];
       // work with p...
    }
    
    0 讨论(0)
  • 2020-12-17 19:27

    Cloning the list is the easiest and best way, because it ensures your list won't change out from under you. If the list is simply too large to clone, consider putting a lock around it that must be taken before reading/writing to it.

    0 讨论(0)
  • 2020-12-17 19:28

    There is no such operation. The best you can do is

    
    lock(collection){
        foreach (object o in collection){
           ...
        }
    }
    
    0 讨论(0)
提交回复
热议问题