管理生成对象池

时间:2015-07-09 08:29:25

标签: c# pool resource-management

我正在开发一个项目,其中地图的各个区域可以动态生成,也可以从文件加载(如果已经生成并保存)。区域仅根据需要加载/生成,并且在不再存在时将被保存和丢弃。 有几个不同的任务将使用此地图的一个或多个区域用于各种目的。例如,这些任务之一将是绘制所有当前可见区域(在任何给定时间大约为9)。另一种方法是获取有关甚至修改区域的信息。 问题是这些任务可能会或可能不会与其他任务使用相同的区域。

由于这些区域相当大,并且生成成本高,因此对于每个任务使用不同的副本会有问题(出于这些和其他原因)。 相反,我认为创建和管理当前加载的区域池是个好主意。新任务将首先检查池中所需的区域。然后,如果它存在,则可以使用它,或者创建一个新的并将其添加到池中。

如果有效,我将如何管理此池?我如何确定任何任务是否不再需要某个区域并且可以安全地丢弃?我是愚蠢的,过于复杂吗?

如果对任何人都很重要,我正在使用c#。

编辑: 既然我更清醒了,那么就像在每个地区增加一个计数器一样简单吗?当计数器达到0时丢弃它?

2 个答案:

答案 0 :(得分:1)

  

如果有效,我将如何管理此池?我如何确定任何任务是否不再需要某个区域并且可以安全地丢弃?

这样做的一个简单方法是使用弱引用:

public class RegionStore
{
  // I'm using int as the identifier for a region.
  // Obviously this must be some type that can serve as
  // an ID according to your application's logic.
  private Dictionary<int, WeakReference<Region>> _store = new Dictionary<int, WeakReference<Region>>();
  private const int TrimThreshold = 1000; // Profile to find good value here.
  private int _addCount = 0;
  public bool TryGetRegion(int id, out Region region)
  {
    WeakReference<Region> wr;
    if(!_store.TryGetValue(id, out wr))
      return false;
    if(wr.TryGetTarget(out region))
      return true;
    // Clean up space in dictionary.
    _store.Remove(id);
    return false;
  }
  public void AddRegion(int id, Region region)
  {
    if(++_addCount >= TrimThreshold)
      Trim();
    _store[id] = new WeakReference<Region>(region);
  }
  public void Remove(int id)
  {
    _store.Remove(id);
  }
  private void Trim()
  {
    // Remove dead keys.
    // Profile to test if this is really necessary.
    // If you were fully implementing this, rather than delegating to Dictionary,
    // you'd likely see if this helped prior to an internal resize.
    _addCount = 0;
    var keys = _store.Keys.ToList();
    Region region;
    foreach(int key in keys)
      if(!_store[key].TryGetTarget(out wr))
        _store.Remove(key);
  }
}

现在您已经存储了Region个对象,但是如果没有其他对它的引用,那么该存储不会阻止它们被垃圾收集。

  

某些任务将修改区域。在这种情况下,我可能会提出更新&#34;在region对象中标记,并从那里更新使用它的所有其他任务。

请注意,这将成为整个应用程序中错误的明确潜在来源。可变性使任何类型的缓存变得复杂。如果你可以转移到一个不可变的模型,它可能会简化一些事情,但是过时的对象的使用带来了它自己的复杂性。

答案 1 :(得分:-1)

好吧,我不知道你的应用程序是如何设计的,但是我很高兴你看看this

您也可以使用静态与其他任务共享变量,但是您可能希望使用块变量来阻止您在其他进程使用它时写入或读取该变量。 (here