0

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

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

如果可行,我将如何管理这个池?我如何确定某个区域是否不再需要任何任务并且可以安全地丢弃?我是不是很傻并且过于复杂了?

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

编辑:现在我更清醒了,是否就像在每个区域中为每个使用它的地方增加一个计数器一样简单?然后在计数器达到 0 时丢弃它?

4

2 回答 2

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对象的存储,但如果不存在对它们的其他引用,该存储不会阻止它们被垃圾收集。

某些任务将是修改区域。在这种情况下,我可能会在区域对象中引发“更新”标志,并从那里更新使用它的所有其他任务。

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

于 2015-07-09T17:52:14.600 回答
-1

好的,我不知道你的应用程序是如何设计的,但我建议你看看这个

您也可以使用 static 与其他任务共享变量,但是您可能希望使用块变量来防止您在其他进程正在使用该变量时写入或读取该变量。(这里

于 2015-07-09T09:33:16.693 回答