Потоки и перебирая меняющиеся коллекции - PullRequest
4 голосов
/ 10 июня 2010

В C # (консольное приложение) я хочу хранить коллекцию объектов.Все объекты одного типа.Я хочу перебрать коллекцию, вызывая метод для каждого объекта.А затем повторите процесс непрерывно.Однако во время итерации объекты могут быть добавлены или удалены из списка.(Сами объекты не будут уничтожены .. просто удалены из списка).Не уверен, что случилось бы с циклом foreach .. или другим подобным методом.Это должно было быть сделано 1000 раз, прежде чем .. вы можете порекомендовать надежный подход?

Ответы [ 3 ]

1 голос
/ 11 июня 2010

Существует также подход на основе копирования. Алгоритм такой:

  1. захватить общую коллекцию
  2. скопировать все элементы из общей коллекции в некоторую локальную коллекцию
  3. снять блокировку с общей коллекции
  4. Перебирать элементы в локальной коллекции

Преимущество этого подхода состоит в том, что вы блокируете общую коллекцию на небольшой период времени (при условии, что общая коллекция относительно мала).

В случае, когда метод, который вы хотите вызвать для каждого элемента коллекции, занимает некоторое значительное время или может заблокировать, тогда подход итерации под общей блокировкой может привести к блокировке других потоков, которые хотят добавить / удалить элементы из общей коллекции

Однако, если тот метод, который вы хотите вызвать для каждого объекта, является относительно быстрым, тогда итерация под общей блокировкой может быть более предпочтительной.

0 голосов
/ 27 августа 2010

Когда я читаю этот пример, я вспоминаю, что вы можете использовать C5 TreeSet / 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 книга .

0 голосов
/ 10 июня 2010

Это классический случай синхронизации в многопоточности.

Только надежный подход и лучший подход - это синхронизация между циклом и добавлением / удалением элементов из списка.

Означает, что вы должны разрешить добавление / удаление только в конце конца и в начале цикла итерации!

что-то вроде этого: -

    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
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...