我有一个关于WeakReferences的问题。
我现在正在编写一个“资源管理器”,它将继续引用创建的纹理对象。我有一个词典,如:
Dictionary<uint, WeakReference>
第一个是,正如您已经猜到的那样,资源ID和第二个参数是资源本身的弱参考。
现在我的资源确实有一种方法可以从他们的所有者(即资源管理器)中释放他们自己。他们在向资源管理器调用方法的同时将此引用传递给它。 ResMgr会查找是否是他保留书签的资源,如果是,则执行以下操作:
WeakReference result;
if (m_Resources.TryGetValue(ResourceId, out result))
{
if (result.IsAlive)
return;
(result.Target as Resource).free(); // free for good
m_Resources.Remove(ResourceId);
}
我遇到的问题是之后的部分:
if (result.IsAlive)
永远不会到达,因为仍有对资源的剩余引用。
问题是,我只有一个有问题资源的参考资料,它会像:
一样自我发布resource.free(); // calls internally its owner (i.e. ResMgr)
resource = null;
我猜左边的引用将是“资源”变量,但我无法将其设置为null,因为我必须首先调用free。相当困难......
我想要实现的目标是资源管理器,它会保留对其拥有的资源的引用,并且只有在没有任何参考文献的情况下才能释放它们。
知道如何以干净的方式解决这个问题吗?
PS:有没有办法以某种方式实际获取引用计数?
提前致谢!
Mfg Imp
答案 0 :(得分:2)
我建议您查看caching或引用计数。弱引用从未打算用作缓存系统
.NET中没有“引用计数”;对象既可以引用,也可以不引用。如果您需要实际的引用计数,那么我建议您使用Rx library RefCountDisposable
,这是一个引用计数IDisposable
。
答案 1 :(得分:2)
我会以不同的方式处理这个问题。我可能在内部保留WeakReference给对象,但我会返回一个硬引用。消费者不应该从资源管理器中删除该项目,除非他们知道他们只有对它的引用而且不需要它。否则,它们应该只是允许系统确定何时删除引用的对象。这样,只要存在对象的(硬)引用,它就会保留在内存中。您可以将其从字典中删除,但是您只需要删除该条目 - 即,对它的任何新请求都必须创建一个新对象,即使其他使用者对旧对象有引用也是如此。如果弱引用不是活动的,则检索过程应该重新创建对象。
public ResourceManager<T>
{
private Dictionary<uint,WeakReference> Cache = new Dictionary<uint,WeakReference>();
public T this[uint key]
{
var obj = (T)this.Cache[key].Target;
if (obj == null)
{
obj = ...recreate resource...
this.Cache[key] = obj;
}
return obj;
}
public void Remove( uint key )
{
this.Cache.Remove(key);
}
}
答案 2 :(得分:1)
如果result.IsAlive为false,则result.Target将为null。
您可能希望查看终结器和/或ConditionalWeakTable,它们可能会帮助您找到解决方案。