如何清除MemoryCache?
我已经使用MemoryCache类创build了一个caching。 我添加一些项目,但是当我需要重新加载caching我想先清除它。 什么是最快的方法来做到这一点? 我应该循环所有的项目,并一次删除一个或有更好的办法吗?
Dispose
现有的MemoryCache并创build一个新的MemoryCache对象。
枚举的问题
MemoryCache.GetEnumerator()备注部分警告:“检索MemoryCache实例的枚举器是一个资源密集型和阻塞操作,因此枚举器不应在生产应用程序中使用。
这就是为什么 ,用GetEnumerator()实现的伪代码解释的原因 :
Create a new Dictionary object (let's call it AllCache) For Each per-processor segment in the cache (one Dictionary object per processor) { Lock the segment/Dictionary (using lock construct) Iterate through the segment/Dictionary and add each name/value pair one-by-one to the AllCache Dictionary (using references to the original MemoryCacheKey and MemoryCacheEntry objects) } Create and return an enumerator on the AllCache Dictionary
由于实现将caching跨多个Dictionary对象拆分,因此必须将所有内容集中到一个集合中,以便交回枚举器。 每次调用GetEnumerator都会执行上面详述的完整复制过程。 新创build的Dictionary包含对原始内部键和值对象的引用,所以您的实际caching数据值不会重复。
文档中的警告是正确的。 避免使用GetEnumerator() – 包括上面使用LINQ查询的所有答案。
一个更好,更灵活的解决scheme
这是清除caching的一种有效方法,只需构build在现有的变更监视基础结构上即可。 它还提供了清除整个caching或只是一个命名的子集的灵活性,并没有上面讨论的问题。
// By Thomas F. Abraham (http://www.tfabraham.com) namespace CacheTest { using System; using System.Diagnostics; using System.Globalization; using System.Runtime.Caching; public class SignaledChangeEventArgs : EventArgs { public string Name { get; private set; } public SignaledChangeEventArgs(string name = null) { this.Name = name; } } /// <summary> /// Cache change monitor that allows an app to fire a change notification /// to all associated cache items. /// </summary> public class SignaledChangeMonitor : ChangeMonitor { // Shared across all SignaledChangeMonitors in the AppDomain private static event EventHandler<SignaledChangeEventArgs> Signaled; private string _name; private string _uniqueId = Guid.NewGuid().ToString("N", CultureInfo.InvariantCulture); public override string UniqueId { get { return _uniqueId; } } public SignaledChangeMonitor(string name = null) { _name = name; // Register instance with the shared event SignaledChangeMonitor.Signaled += OnSignalRaised; base.InitializationComplete(); } public static void Signal(string name = null) { if (Signaled != null) { // Raise shared event to notify all subscribers Signaled(null, new SignaledChangeEventArgs(name)); } } protected override void Dispose(bool disposing) { SignaledChangeMonitor.Signaled -= OnSignalRaised; } private void OnSignalRaised(object sender, SignaledChangeEventArgs e) { if (string.IsNullOrWhiteSpace(e.Name) || string.Compare(e.Name, _name, true) == 0) { Debug.WriteLine( _uniqueId + " notifying cache of change.", "SignaledChangeMonitor"); // Cache objects are obligated to remove entry upon change notification. base.OnChanged(null); } } } public static class CacheTester { public static void TestCache() { MemoryCache cache = MemoryCache.Default; // Add data to cache for (int idx = 0; idx < 50; idx++) { cache.Add("Key" + idx.ToString(), "Value" + idx.ToString(), GetPolicy(idx)); } // Flush cached items associated with "NamedData" change monitors SignaledChangeMonitor.Signal("NamedData"); // Flush all cached items SignaledChangeMonitor.Signal(); } private static CacheItemPolicy GetPolicy(int idx) { string name = (idx % 2 == 0) ? null : "NamedData"; CacheItemPolicy cip = new CacheItemPolicy(); cip.AbsoluteExpiration = System.DateTimeOffset.UtcNow.AddHours(1); cip.ChangeMonitors.Add(new SignaledChangeMonitor(name)); return cip; } } }
解决方法是:
List<string> cacheKeys = MemoryCache.Default.Select(kvp => kvp.Key).ToList(); foreach (string cacheKey in cacheKeys) { MemoryCache.Default.Remove(cacheKey); }
var cacheItems = cache.ToList(); foreach (KeyValuePair<String, Object> a in cacheItems) { cache.Remove(a.Key); }
如果性能不是问题,那么这个不错的单线程将会诀窍:
cache.ToList().ForEach(a => cache.Remove(a.Key));
似乎有一个修剪方法。
所以要清除你刚刚做的所有内容
cache.Trim(100)
编辑:挖了一些之后,似乎看着修剪是不值得你的时间
如何清除System.Runtime.Caching.MemoryCache
你也可以做这样的事情:
Dim _Qry = (From n In CacheObject.AsParallel() Select n).ToList() For Each i In _Qry CacheObject.Remove(i.Key) Next
穿越这个,并在此基础上,写了一个更有效,同时清晰的方法:
public void ClearAll() { var allKeys = _cache.Select(o => o.Key); Parallel.ForEach(allKeys, key => _cache.Remove(key)); }
有点改进的马格利特答案。
var cacheKeys = MemoryCache.Default.Where(kvp.Value is MyType).Select(kvp => kvp.Key).ToList(); foreach (string cacheKey in cacheKeys) { MemoryCache.Default.Remove(cacheKey); }
- App.Config转换为Visual Studio 2010中不是Web项目的项目?
- foreach + break vs linq FirstOrDefault性能差异
- 从Process StandardOutput获取值
- 不信任的entity framework表决 – 与.NET 4相关?
- 尝试方法'System.Web.Helpers.Json..cctor()'来访问方法'System.Web.Helpers.Json.CreateSerializer()'失败
- 什么时候应该使用TaskCompletionSource <T>?
- Microsoft .NET 4.0完整框架和客户端configuration文件之间的区别
- 可以在.Net 4.0中使用Tuple的实际示例?
- “此程序集由比当前加载的运行时更新的运行时构build,无法加载”