2010-06-10 110 views
4

在C#中(控制台应用程序)我想保存对象的集合。所有对象都是相同的类型。 我想迭代通过调用每个对象的方法的集合。然后不断重复这个过程。 但是在迭代过程中,可以从列表中添加或删除对象。 (对象本身不会被销毁,只是从列表中删除)。 不确定foreach循环会发生什么......或其他类似的方法。 这个已经被做1000次之前..你能推荐一个可靠的方法吗?线程化和迭代通过更改集合

回答

0

这是多线程同步的经典案例。

只有坚实的方法和更好的方法才能在循环和列表中添加/删除项目之间同步。

意味着您应该只允许在结束和迭代循环开始时添加/删除!

一些这样的事: -

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 
1

另外也复制为基础的方法。 的算法是这样的:

  1. 采取锁共享集合
  2. 副本的所有项目从共享收集到一些地方收集
  3. 释放锁在共享集合
  4. 遍历本地收集
  5. 项目

这种方法的优点是您可以在共享收集上锁定一段时间(假设共享收集相对较小)。

如果您希望在每个集合项目上调用的方法需要花费相当多的时间才能完成或者可以阻止,那么在共享锁下进行迭代的方法可能会导致阻止想要从共享集合中添加/删除项目的其他线程

但是,如果您想要在每个对象上调用的方法相对较快,那么在共享锁下进行迭代更为可取。

0

我读到这个例子时想到的是你可以使用C5TreeSet/TreeBag。它确实需要有一种方法来订购您的物品,但Tree系列的优势在于它们提供了一种Snapshot方法(C5.IPersistentSorted的成员),使您可以轻松制作集合状态的快照而无需做一个完整的重复。

如:

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

C5还提供了一个简单的方法来“适用于所有”,并与.NET 2.0兼容:

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

需要注意的是快照应布置很重要否则随后对基本集合进行修改会导致性能下降。

这个例子来自非常彻底的C5 Book