【发布时间】:2010-10-12 12:50:07
【问题描述】:
我熟悉WeakReference,但我正在寻找一种仅在内存不足时才被清除的引用类型,而不仅仅是每次 gc 运行时(就像 Java 的 SoftReference )。我正在寻找一种实现内存敏感缓存的方法。
【问题讨论】:
标签: .net garbage-collection weak-references soft-references
我熟悉WeakReference,但我正在寻找一种仅在内存不足时才被清除的引用类型,而不仅仅是每次 gc 运行时(就像 Java 的 SoftReference )。我正在寻找一种实现内存敏感缓存的方法。
【问题讨论】:
标签: .net garbage-collection weak-references soft-references
ASP.NET 缓存为您提供所需的内存敏感行为,但缺点是所有内容都需要唯一键。但是,您应该能够持有对已放置在 ASP.NET 缓存中的对象的 WeakReference。缓存的强引用将阻止 GC,直到缓存决定需要清除它以释放内存。 WeakReference 使您可以访问对象,而无需使用缓存键进行查找。
Foo cachedData = new Foo();
WeakReference weakRef = new WeakReference( cachedData );
HttpRuntime.Cache[Guid.NewGuid().ToString()] = cachedData;
...
if ( weakRef.IsAlive )
{
Foo strongRef = weakRef.Target as Foo;
}
你可以通过扩展 WeakReference 来创建一个 SoftReference 类
class SoftReference : WeakReference
{
public SoftReference( object target ) : base( target )
{
HttpRuntime.Cache[Guid.NewGuid().ToString()] = target;
}
}
您还需要覆盖 Target 上的设置器,以确保任何新目标都进入缓存。
【讨论】:
也许 ASP.NET Cache 类 (System.Web.Caching.Cache) 可能有助于实现您想要的?如果内存不足,它会自动删除对象:
Here's an article 展示了如何在 Windows 窗体应用程序中使用 Cache 类。
【讨论】:
除了 ASP.NET 缓存之外,还有来自 Microsoft 模式和实践组的缓存应用程序块。
【讨论】:
虽然SoftReference 似乎是一种实现内存缓存的便捷方式,但它需要Java 运行时做出一些随意的决定,以确定保留对象的好处是否超过存储它的成本。不幸的是,运行时有关保留对象的实际成本的信息有限(请记住,实际成本可能包括应用程序的内存使用对其他应用程序的影响),并且实际上没有关于保留对象的好处的信息.
如果即使在没有外部强引用存在的情况下保留一个对象也是值得的,那么缓存应该保留对它的强引用(至少只要它看起来有价值)。如果将对象保存在缓存中的好处只会在外部引用存在的情况下扩展(例如,因为生成实例很便宜,但是拥有两个保存相同数据的逻辑实体使用相同的实例来保存它们将有助于这些实体之间的比较),应该使用WeakReference。
顺便说一句,如果我有我的 druthers,.net 将支持另一种我在任何平台上都没有见过的引用:“其他人感兴趣”的引用,它将与 @ 类型一起使用987654323@。 “其他人感兴趣”的引用可以用作强引用,但如果对其目标的唯一强引用是“其他人感兴趣”,则适当配置的 WeakReference 将无效。在使用并发 GC 时,这样的概念可以提高效率,在弱事件处理程序会重复生成对其目标的强引用的情况下。如果没有人真正对事件处理程序对其目标执行的操作感兴趣,那么最好处理程序可以取消订阅。
【讨论】:
不,没有等价物。 WeakReference 不能胜任这项工作有什么特别的原因吗?
这里有一个与你类似的问题:
Why doesn't .NET have a SoftReference as well as a WeakReference, like Java?
【讨论】: