假设我有一个类似下面的代码片段,它返回Context.Cache [“someComplexObject”]的内容:
public class Something {
private static SortedDictionary<Guid, Object> ComplexObjectCache
{
get
{
if (Context.Cache["someComplexObject"] == null)
{
FillCache();
}
return (SortedDictionary<Guid, Object>)Context.Cache["someComplexObject"];
}
set
{
Int32 seconds = (new Random()).Next(120, 180);
Context.Cache.Add(
"someComplexObject",
value,
null,
DateTime.Now.AddSeconds(seconds),
System.Web.Caching.Cache.NoSlidingExpiration,
System.Web.Caching.CacheItemPriority.NotRemovable,
null
);
}
}
}
在用户控件中,假设我有:
Object o = Something.ComplexObjectCache[someGuid];
/*
do some other stuff ...
*/
DoSomethingWith(o);
偶尔会出现非常罕见的情况,当我看到 DoSomethingWith(o)被击中时,我会看到异常会让我相信 o 不再在记忆中。我97%确定没有其他并行进程发生,除了缓存正在做什么。我看到其他奇怪的现象会让我相信缓存密钥是空的还是不完整的。
缓存是否可以真正从内存中删除对象,即使其他地方仍有指向它的指针?如果是这样,我该怎么做呢?
在进一步挖掘之后,我发现我们有一个相关的缓存项(索引),它在“主”缓存项之前到期时会导致问题。我重做了这个实体的缓存代码,将这两个结构存储在一起在一个Object数组中。这似乎解决了这个问题。
您没有足够的信息来解决问题。因此,我会查看答案,并勾选答案,以便最准确地解决给出的问题。
答案 0 :(得分:1)
缓存永远不会从内存中删除任何内容。
垃圾收集器从内存中删除对象,只有在没有对该对象的引用时才会发生这种情况。因此,只要您有对象的引用,即使它们从缓存中删除,也不会从内存中删除对象。
(缓存可以在请求中删除对象的引用。由于多个线程可以同时处理请求,因此可能会在不同的线程中发生某些事情,导致缓存丢弃项目。缓存不能等到所有线程都空闲丢弃项目,然后它可能永远无法做到这一点,你会耗尽内存。)
答案 1 :(得分:1)
是的,它会。如果为内存按下Web服务器,即使这样的代码也无法打印&#34; foo&#34;。
Context.Cache.Add(
"someComplexObject",
"foo",
null,
DateTime.Now.AddSeconds(seconds),
System.Web.Caching.Cache.NoSlidingExpiration,
System.Web.Caching.CacheItemPriority.NotRemovable,
null
);
Response.Write(Cache["someComplexObject").ToString());
你需要做一些聪明的事情,比如
string val = "foo";
Context.Cache.Add(
"someComplexObject",
val,
null,
DateTime.Now.AddSeconds(seconds),
System.Web.Caching.Cache.NoSlidingExpiration,
System.Web.Caching.CacheItemPriority.NotRemovable,
null
);
Response.Write(val.ToString());
此外,您需要在读取或写入缓存时锁定。您可以使用ReaderWriterLock(或类似)。这是为了避免在写入高速缓存时进行读取(并在读取高速缓存时写入)。
我已为SixPack library实施了几个缓存,您可能会觉得这些缓存很有趣,例如请参阅此CacheController类。
作为旁注,这个类比你需要的要复杂得多,因为它是允许你像这样缓存的系统的一部分:
[Cached]
public class MyTime : ContextBoundObject
{
[CachedMethod(1)]
public DateTime Get()
{
Console.WriteLine("Get invoked.");
return DateTime.Now;
}
public DateTime GetNoCache()
{
Console.WriteLine("GetNoCache invoked.");
return DateTime.Now;
}
}
答案 2 :(得分:0)
只要感觉如此,缓存就可以自由地删除对象。即它可以在您添加后立即检测内存压力并丢弃项目。
你真的不应该使用Cache传递对象。缓存是缓存 - 存储对象以便将来加速,但在单个请求期间使用其他方法传递对象。另请注意,与Items不同的是,共享缓存。
答案 3 :(得分:0)
是的,您的FillCache方法正在填充缓存,但是在此之间和检索缓存内容之间有时间。在这段时间内,您的缓存可能会失效。尝试从FillCache方法返回,以便始终拥有可靠的引用:
private SortedDictionary<Guid, Object> ComplexObjectCache()
{
if (Context.Cache["someComplexObject"] == null)
{
var cacheItems = FillCache();
return cacheItems;
}
return (SortedDictionary<Guid, Object>)Context.Cache["someComplexObject"];
}