Использовать список однопоточных объектов в цикле параллельной обработки - PullRequest
0 голосов
/ 23 ноября 2018

Предположим, что я обрабатываю 1000 элементов в параллельном цикле обработки.
Для обработки элемента иногда требуется объект Calculation со специализированным алгоритмом, который должен быть однопоточным и создавать его несколько дорого.

Я рассматривал создание класса контейнера с List<Calculation>, который можно попросить дать один такой объект, когда он свободен, или создать новый объект Calculation иным способом.

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

Существуют ли шаблоны или типы C #для этого сценария, который вы знаете?

Ответы [ 2 ]

0 голосов
/ 23 ноября 2018

Я успешно реализовал этот вид пула потоков, используя коллекцию ConcurrentBag, а не список.Это потокобезопасно.Примерно так:

  ConcurrentBag<Calculation> active = new ConcurrentBag<Calculation>();

  Calculation calc;
  if ( idle.IsEmpty || !idle.TryTake(calc)) {
       calc = new Calculation();
  }

  /* start the Calculation object */
  /* when it completes toss it in the bag for reuse ... */
  idle.Add (calc);

Сумка похожа на список, но неупорядочена.Это хорошо для того, что вы хотите сделать.

0 голосов
/ 23 ноября 2018

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

Вы можете управлять пулом вручную.Возьмите предметы по необходимости и верните их после использования.Это склонно к ошибкам.Вы можете забыть вернуть элементы (оставив их в GC, возможно, удерживая ресурсы, такие как дескрипторы файлов).Вы также можете вернуться рано, что приведет к одновременной работе двух потребителей пула с одним и тем же объектом.

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

По всей вероятности, вам просто нужно будет правильно использовать пул объектов.На ум приходит образец типа

var obj = pool.Take();
try {
 Use(obj);
}
finally {
 pool.Return(obj);
}

.Вы также можете использовать using для этого.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...