2009-04-16 53 views
1

我为我正在开发的网站创建了自己的缓存管理器,并且我正在寻找在某些情况下清除缓存的最佳方法。HttpRuntime关闭不会从广告中删除缓存中的项目

我发现很多文章说的正确方法清除缓存是调用HttpRuntime.Close()

然而,在我的单元测试设置我称密封功能HttpRuntime.Close()和缓存不是被清除。

我希望它来执行类似的东西来

foreach (DictionaryEntry cacheItem in HttpRuntime.Cache) 
{ 
    HttpRuntime.Cache.Remove(cacheItem.Key.ToString()); 
} 

foreach循环工作在我的包裹作用很大,但关闭()从来没有作品的权利。

我误解了HttpRuntime.Close()的目的,还是有什么更邪恶的在这里?

回答

9

不要使用Close,它比文档说得多。而文档也说没有用它在处理正常的请求......

这是关闭()的反射源:

[SecurityPermission(SecurityAction.Demand, Unrestricted=true)] 
public static void Close() { 
    if (_theRuntime.InitiateShutdownOnce()) { 
     SetShutdownReason(ApplicationShutdownReason.HttpRuntimeClose, "HttpRuntime.Close is called"); 
     if (HostingEnvironment.IsHosted) { 
      HostingEnvironment.InitiateShutdown(); 
     } else { 
      _theRuntime.Dispose(); 
     } 
    } 
} 

而且,你不能遍历集合,并从中删除项目同时,因为这使枚举无效。

所以,试试这个来代替,这不会改变它遍历:

List<string> toRemove = new List<string>(); 
foreach (DictionaryEntry cacheItem in HttpRuntime.Cache) { 
    toRemove.Add(cacheItem.Key.ToString()); 
} 
foreach (string key in toRemove) { 
    HttpRuntime.Cache.Remove(key); 
} 

话虽这么说,真的,你应该尝试使用缓存依赖于为您自动清除无效的缓存条目,然后所有这些变得没有必要。

+0

其实我已经测试了我放在我的问题中的代码,它工作正常。我理解枚举的问题,但由于某些原因,缓存在遍历列表时移除项目似乎没有问题。 – Joseph 2009-04-16 20:37:21

+0

虽然这不是我的问题。我所说的是,如果我在缓存中有4个项目,并且按照我所描述的方式循环访问,那么缓存最终会包含0个项目。但是,当我使用Close()时,这4个项目仍然存在。 – Joseph 2009-04-16 20:38:23

+0

这是因为文档陈述的东西不是完整的真相。Close()并不意味着用于清除缓存。 – Lucero 2009-04-16 20:42:03

4

我理解这个问题用枚举,但由于某些原因,缓存似乎不具有移除项目,同时通过名单走的问题。

如果你深入到细节的实现,你会发现枚举由CacheSingle.CreateEnumerator创建一个新的Hashtable实例枚举创建。

这就是为什么你可以在foreach循环中进行删除。

0

你可以简单地实现自己的Cache类,检查以下之一:

public sealed class YourCache<T> 
{ 
    private Dictionary<string, T> _dictionary = new Dictionary<string, T>(); 

    private YourCache() 
    { 
    } 

    public static YourCache<T> Current 
    { 
     get 
     { 
      string key = "YourCache|" + typeof(T).FullName; 
      YourCache<T> current = HttpContext.Current.Cache[key] as YourCache<T>; 
      if (current == null) 
      { 
       current = new YourCache<T>(); 
       HttpContext.Current.Cache[key] = current; 
      } 
      return current; 
     } 
    } 

    public T Get(string key, T defaultValue) 
    { 
     if (string.IsNullOrWhiteSpace(key)) 
      throw new ArgumentNullException("key should not be NULL"); 

     T value; 
     if (_dictionary.TryGetValue(key, out value)) 
      return value; 

     return defaultValue; 
    } 

    public void Set(string key, T value) 
    { 
     if (key == null) 
      throw new ArgumentNullException("key"); 

     _dictionary[key] = value; 
    } 

    public void Clear() 
    { 
     _dictionary.Clear(); 
    } 
} 

你可以从缓存中调用的项目,甚至明确他们使用下列内容:

// put something in this intermediate cache 
YourCache<ClassObject>.Current.Set("myKey", myObj); 

// clear this cache 
YourCache<ClassObject>.Current.Clear();