C#“共享指针”用于替代内存管理?

我正在寻找一种在C#中执行此操作的方法:

  1. Asker对象将向Giver对象询问Resource对象。
  2. 当被问及时,Giver将在其字典中搜索现有的匹配资源。 如果找到,它将返回Resource的引用; 否则,它将从数据库数据创建一个新的资源,在Dictionary中保存该引用,最后返回引用。
  3. Asker可能会多次请求相同的资源,在这种情况下,Giver将从字典中返回相同的资源相同的次数。
  4. Asker可能在任何时候都没有使用给定的资源,在这种情况下,它对资源没有任何进一步的作用。

  5. 问题:Giver如何检测任何不再使用的资源并将其从字典中删除? 优选地,Giver应该在没有Asker帮助的情况下执行此操作。

这可能吗? 我似乎无法解决这个问题。

编辑:谢谢大家的好评。 尤其是WeakReferences。 我不知道他们在那里。 但我有两个主要目标,我可以指明更清楚。

  1. 给予者不应该依赖Asker来获得通知。
  2. 在使用给定资源时, 所有引用必须指向相同的资源,以便对资源的修改反映在使用相同资源的所有位置。

编辑:[删除了错误的代码块]

首先,您所谈论的是IDisposable接口背后的基本思想:资源发布的确定性方式。 虽然它的主要用途是在与需要显式释放(或与执行该操作的对象进行交互)的非托管资源进行交互时,但其用途并不局限于此。

不幸的是,它失败了你的最后一个要求:因为它是确定性的,它必须由某人调用。 这个人必须是Asker。

我能想出的唯一解决方案是在Giver对象中使用WeakReference类。 这允许您维护对实例的引用,该实例不会阻止它被垃圾回收(在收集之后,您的引用变为null )。

不幸的是,这不是确定性的。 在实际收集对象后,您的引用将变为null (并且IsAlive将为false ),这不保证在任何特定时间(或在应用程序的生命周期内)发生。

考虑到这些警告,你可以这样:

 public class Giver { private Dictionary cache = new Dictionary(); public object GetResource(string resourceName) { WeakReference output; object returnValue = null; if(cache.TryGetValue(resourceName, out output)) { if(output.IsAlive) returnValue = output.Target; if(returnValue == null) cache.Remove(resourceName); } if(returnValue == null) { returnValue = ...; // get the actual resource cache.Add(resourceName, new WeakReference(returnValue)); } return returnValue; } } 

所有这些function都封装在System.Web.Caching.Cache

这可以在ASP.NET外安全使用,并具有到期,重新加载的机制……

您可以将WeakReference存储到字典中的资源而不是资源本身。 这不会阻止资源被垃圾收集。

当您从字典中获取值(弱引用)时,您需要获取Target并查看它是否为空。 如果是,则资源已被垃圾收集,您需要重新创建它。 否则,您可以将目标作为缓存资源返回。

我不相信对WeakReference “重要”程度有多大的控制权 – 例如,我认为你不能说它应该像gen2一样。 当然,你可以有一些其他的数据结构,以确保任何资源至少(比方说)5分钟被缓存,通过长时间保持对它的强引用。

如果您采用这种方法,您可能还需要定期浏览字典并清除目标已被垃圾收集的条目,以避免字典中出现无用的条目。 如果这组键是固定的而不是太大,那么这可能不值得,特别是考虑到你可能需要的同步。

Asker必须告诉Giver它不再使用资源。

此时, Giver应该删除资源。

Observer模式可以在这里提供帮助。

你可能需要一个Dictionary [string,WeakReference]。 MSDN有一个示例,说明如何使用它们来实现或多或少的系统要求:

http://msdn.microsoft.com/en-us/library/system.weakreference.aspx

只需向下滚动到“示例”部分,其中显示了如何实现资源缓存。

WeakReference不会将对象锁定,当它们指向的对象被垃圾回收器回收时,它们只是变为null

您可以在Giver使用WeakReference类 。

一种方法是使用弱引用。 这是我几年前写的关于这种方法的文章:

http://www.devx.com/dotnet/Article/36286

继Oded的评论之后,这里是IObserver接口的链接,可以帮助您入门:

http://msdn.microsoft.com/en-us/library/dd783449.aspx