我为我正在开发的网站创建了自己的缓存管理器,我希望找到在某些情况下清除缓存的最佳方法。
我发现很多文章说清除缓存的正确方法是调用HttpRuntime.Close()
但是,在我的单元测试设置中,我调用了封装函数HttpRuntime.Close(),并且没有清除缓存。
我希望它能执行类似于
的操作foreach (DictionaryEntry cacheItem in HttpRuntime.Cache)
{
HttpRuntime.Cache.Remove(cacheItem.Key.ToString());
}
foreach循环在我的封装函数中运行良好,但Close()永远不能正常工作。
我是否误解了HttpRuntime.Close()的目的,还是有更邪恶的事情发生在这里?
答案 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();