关于WeakReferences的问题

时间:2010-05-15 15:49:42

标签: c#

我有一个关于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

3 个答案:

答案 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,它们可能会帮助您找到解决方案。