Asp.net HttpRuntime Close不会从公布的缓存中删除项目

Asp.net HttpRuntime Close不会从公布的缓存中删除项目,asp.net,caching,asp.net-2.0,Asp.net,Caching,Asp.net 2.0,我为我正在开发的一个网站创建了自己的缓存管理器,我一直在寻找在某些情况下清除缓存的最佳方法 我发现很多文章都说清除缓存的正确方法是调用HttpRuntime.Close 但是,在我的单元测试设置中,我调用了封装的函数HttpRuntime.Close,缓存没有被清除 我希望它能执行类似的操作 foreach (DictionaryEntry cacheItem in HttpRuntime.Cache) { HttpRuntime.Cache.Remove(cacheItem.Key.T

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

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

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

我希望它能执行类似的操作

foreach (DictionaryEntry cacheItem in HttpRuntime.Cache)
{
    HttpRuntime.Cache.Remove(cacheItem.Key.ToString());
}
foreach循环在我封装的函数中工作得很好,但是Close永远不会正常工作


我是不是误解了HttpRuntime.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);
}

也就是说,实际上,您应该尝试使用缓存依赖项来自动清除无效的缓存条目,然后所有这些都变得不必要。

不要使用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);
}
也就是说,实际上,您应该尝试使用缓存依赖项来自动清除无效的缓存条目,然后所有这些都变得不必要了

我理解枚举的问题,但由于某种原因,在遍历列表时,缓存似乎没有在删除项时遇到问题

如果深入到详细实现,您会发现枚举数是由CacheSSingle.CreateEnumerator创建的,将为枚举创建一个新的哈希表实例

这就是为什么可以在foreach循环中执行remove

我理解枚举的问题,但由于某种原因,在遍历列表时,缓存似乎没有在删除项时遇到问题

如果深入到详细实现,您会发现枚举数是由CacheSSingle.CreateEnumerator创建的,将为枚举创建一个新的哈希表实例


这就是为什么您可以在foreach循环中执行删除操作。

您只需实现自己的缓存类,请选中以下一个:

 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();

您可以简单地实现自己的缓存类,请检查以下内容:

 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();

实际上,我已经测试了我在问题中输入的代码,它运行良好。我理解枚举的问题,但出于某种原因,在遍历列表时,缓存似乎没有在删除项时遇到问题。但这不是我真正的问题。我想说的是,如果我在缓存中有4个项目,我按照我描述的方式循环,那么缓存最终会有0个项目。然而,当我使用Close时,这4项仍然存在。这是因为文档中陈述了一些不完全真实的东西。Close不是用来清除缓存的。哎哟,好的,谢谢你的提醒。缓存依赖项是什么意思?当条目添加到缓存中时,您可以为它们提供依赖项,如超时、文件、另一个缓存条目等,如果此依赖项触发,将清除缓存项。请看,实际上我已经测试了我在问题中输入的代码,它运行良好。我理解枚举的问题,但出于某种原因,在遍历列表时,缓存似乎没有在删除项时遇到问题。但这不是我真正的问题。我想说的是,如果我在缓存中有4个项目,我按照我描述的方式循环,那么缓存最终会有0个项目。然而,当我使用Close时,这4项仍然存在。这是因为文档中陈述了一些不完全真实的东西。Close不是用来清除缓存的。哎哟,好的,谢谢你的提醒。缓存依赖项是什么意思?当条目添加到缓存中时,您可以为它们提供依赖项,如超时、文件、另一个缓存条目等,如果此依赖项触发,将清除缓存项。另见