我正在尝试为我正在编写的小爱好游戏编写一个简单的资源管理器。此资源管理器需要执行的任务之一是卸载未使用的资源。我可以想到以两种方式做到这一点:
当一个物体不再需要时 它必须是对资源的引用 调用资源管理器的方法 表示它不再使用它; 或
当一个物体不再需要时 简单地说,参考资源 将其设置为null。然后当 要求资源管理器卸载 未使用的资源,它得到了 引用计数(通过反射?) 每个资源。如果引用计数 是一个(资源经理会 参考资源), 卸载资源。
有没有办法在C#中实现第二个解决方案? 感谢。
答案 0 :(得分:31)
夫妻俩。首先,对象不参考计数;参考计数方案具有循环参考问题,其中两个对象相互引用但是否则是不可访问的,从而泄漏。 .NET使用标记和扫描方法,不使用引用计数。
其次,尽管使用弱引用的建议并不可怕,但它也不是一个扣篮。您出于性能原因正在构建缓存。 (我假设您对应用程序的性能特征进行仔细,经验,实际的研究已经令人信服地证明,为了获得可接受的性能,缓存策略是必要的;如果不是这样,那么您就是过早地做出这些决定。)缓存必须具有关于何时释放其资源的POLICY,否则就是内存泄漏。
您如何知道GC政策和您的政策是等效的政策? GC的设计并未考虑到特定的性能需求。也就是说,它旨在释放真正属于垃圾的资源,而不是为了达到您想到的任何特定性能目标。通过将决策委派给GC,您可以放弃根据性能需求调整缓存策略的能力。
答案 1 :(得分:12)
听起来你可以从资源管理器中使用WeakReference
。 GC将完成剩下的工作。你需要做一点点投射,但它会很简单,并且会起作用。
class Manager {
Dictionary<string, WeakReference> refs =
new Dictionary<string, WeakReference>();
public object this[string key] {
get {
WeakReference wr;
if (refs.TryGetValue(key, out wr)) {
if(wr.IsAlive) return wr.Target;
refs.Remove(key);
}
return null;
}
set {
refs[key] = new WeakReference(value);
}
}
}
static void Main() {
Manager mgr = new Manager();
var obj = new byte[1024];
mgr["abc"] = obj;
GC.Collect(GC.MaxGeneration, GCCollectionMode.Forced);
Console.WriteLine(mgr["abc"] != null); // true (still ref'd by "obj")
obj = null;
GC.Collect(GC.MaxGeneration, GCCollectionMode.Forced);
Console.WriteLine(mgr["abc"] != null); // false (no remaining refs)
}
答案 2 :(得分:2)
我们已经在.NET中有一个名为垃圾收集器的资源管理器。因此,一种非常有效的方法是将引用设置为null并且不执行任何操作。
更直接的答案:不,没有办法将参考文献转换为。
您可能想要学习WeakReference class或使用缓存系统。
答案 3 :(得分:1)
确保资源管理器将WeakReference
用于您的资源。这样,当没有其他人引用资源时,他们就有资格进行垃圾收集。
答案 4 :(得分:0)
正如其他用户已经说过的那样,您尝试实现的目标已经由GC完成,可以使用WeakReference进行微调。
这意味着在.NET,Java等托管环境中,这是一个无问题。
由于低级框架架构将您与内存管理隔离开来,如果您仍然需要这种功能,我强烈建议您查看自己的代码架构,因为这会意味着您正在做某种不好的事情 - 内存管理实践