开发者

Threading and iterating through changing collections

开发者 https://www.devze.com 2023-01-03 10:54 出处:网络
In C# (console app) I want to hold a collection of objects.All objects are of same type. I want to iterate through the collection calling a method on each object.And then repeat the process continuous

In C# (console app) I want to hold a collection of objects. All objects are of same type. I want to iterate through the collection calling a method on each object. And then repeat the process continuously. However during iteration objects can be added or removed from the list. (The objec开发者_开发知识库ts themselves will not be destroyed .. just removed from the list). Not sure what would happen with a foreach loop .. or other similar method. This has to have been done 1000 times before .. can you recommend a solid approach?


There is also copy based approach. The algorithm is like that:

  1. take the lock on shared collection
  2. copy all items from shared collection to some local collection
  3. release lock on shared collection
  4. Iterate over items in local collection

The advantage of this approach is that you take the lock on shared collection for small period of time (assuming that shared collection is relatively small).

In case when method that you want to invoke on every collection item takes some considerable time to complete or can block then the approach of iterating under shared lock can lead to blocking other threads that want to add/remove items from shared collection

However if that method that you want to invoke on every object is relatively fast then iterating under shared lock can be more preferable.


This is classic case of syncronization in multithreading.

Only solid approach and better approach would be syncronization between looping and addition/deletion of items from list.

Means you should allow addition/deletion only at end of end and start of iterating loop!

some thing like this:-

    ENTER SYNC_BLOCK
      WAIT FOR SYNC_BLOCK to be available

      LOOP for items/ call method on them.

     LEAVE SYNC_BLOCK


     ENTER SYNC_BLOCK
      WAIT FOR SYNC_BLOCK to be available

     Add/Delete items

 LEAVE SYNC_BLOCK


What comes to mind when I read this example is that you could use a C5 TreeSet/TreeBag. It does require that there be a way to order your items, but the advantage of the Tree collections is that they offer a Snapshot method (A member of C5.IPersistentSorted) that allows you to make light-weight snapshots of the state of the collection without needing to make a full duplicate.

e.g.:

using(var copy = mySet.Snapshot()) {
  foreach(var item in copy) {
    item.DoSomething();
  }
}

C5 also offers a simple way to "apply to all" and is compatible with .NET 2.0:

using(var copy = mySet.Snapshot()) {
  copy.Apply(i => i.DoSomething());
}

It's important to note that the snapshot should be disposed or you will incur a small performance penalty on subsequent modifications to the base collection.

This example is from the very thorough C5 Book.

0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号