我正在开发一个项目,其中地图的各个区域可以动态生成,也可以从文件加载(如果已经生成并保存)。区域仅根据需要加载/生成,并且在不再存在时将被保存和丢弃。 有几个不同的任务将使用此地图的一个或多个区域用于各种目的。例如,这些任务之一将是绘制所有当前可见区域(在任何给定时间大约为9)。另一种方法是获取有关甚至修改区域的信息。 问题是这些任务可能会或可能不会与其他任务使用相同的区域。
由于这些区域相当大,并且生成成本高,因此对于每个任务使用不同的副本会有问题(出于这些和其他原因)。 相反,我认为创建和管理当前加载的区域池是个好主意。新任务将首先检查池中所需的区域。然后,如果它存在,则可以使用它,或者创建一个新的并将其添加到池中。
如果有效,我将如何管理此池?我如何确定任何任务是否不再需要某个区域并且可以安全地丢弃?我是愚蠢的,过于复杂吗?
如果对任何人都很重要,我正在使用c#。
编辑: 既然我更清醒了,那么就像在每个地区增加一个计数器一样简单吗?当计数器达到0时丢弃它?
答案 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)