在并行处理循环中使用单线程对象列表

时间:2018-11-23 13:24:38

标签: c# parallel-processing

假设我在一个并行处理循环中处理了1000个项目。
处理项目有时需要使用带有专用算法的Calculation对象,该算法必须是单线程的,并且创建起来有些昂贵。

我当时正在考虑创建一个带有List<Calculation>的容器类,可以要求它在空闲时提供一个这样的对象,否则将创建一个新的Calculation对象。

容器类内部的管理必须手动进行编码,并且必须针对不同线程中的错误进行证明,因此我认为可能会容易忽略一些故障。

您是否知道此方案的C#模式或类型?

2 个答案:

答案 0 :(得分:2)

这称为对象池。如果创建或销毁对象的成本很高并且有重用的机会,则很有用。

您可以手动操作池。必要时取物品,用后退回。这很容易出现错误。您可以忘记返回项目(将项目留给GC可能会占用诸如文件句柄之类的资源)。您还可以提早返回,这将导致池的两个使用者同时对同一个对象进行操作。

您还可以使用object resurrection确定何时删除某项并将其自动拉入池中。我认为这在实践中不起作用。根据GC的行为,这可能导致资源消耗的巨大波动。还有很多潜在的非常严重的错误的可能性。

很可能您只需要正确使用对象池即可。像

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

浮现在脑海。您也可以为此使用using

答案 1 :(得分:1)

我已经通过使用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);

一个包就像一个列表,但无序。这对您想做的事很好。