HttpRuntime Close不会像宣传的那样从缓存中删除项目

时间:2009-04-16 20:29:45

标签: asp.net caching asp.net-2.0

我为我正在开发的网站创建了自己的缓存管理器,我希望找到在某些情况下清除缓存的最佳方法。

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

但是,在我的单元测试设置中,我调用了封装函数HttpRuntime.Close(),并且没有清除缓存。

我希望它能执行类似于

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

foreach循环在我的封装函数中运行良好,但Close()永远不能正常工作。

我是否误解了HttpRuntime.Close()的目的,还是有更邪恶的事情发生在这里?

3 个答案:

答案 0 :(得分:9)

不要使用Close,它比文档说的更多。文档还说在处理正常请求时不使用它......

这是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);
}

实际上,你应该尝试使用缓存依赖关系来自动清除无效的缓存条目,然后这一切都变得不必要了。

答案 1 :(得分:4)

  
    

我理解枚举的问题,但出于某种原因,在遍历列表时,删除项目似乎没有问题。

  

如果深入查看详细实现,您会发现Enumerator是由CacheSingle.CreateEnumerator创建的,为枚举创建了一个新的Hashtable实例。

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

答案 2 :(得分: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();