How to Clear Memorycache

How to clear MemoryCache?

Dispose the existing MemoryCache and create a new MemoryCache object.

Is this a good solution to clear a C# MemoryCache?

The issue with your solution is that it introduces a possible race condition which would need ugly locks or other thread syncronization solutions.

Instead, use the built-in solution.

You can use a custom ChangeMonitor class to clear your items from the cache. You can add a ChangeMonitor instance to the ChangeMonitors property of the CacheItemPolicy you set when you call MemoryCache.Set.

For example:

class MyCm : ChangeMonitor
{
string uniqueId = Guid.NewGuid().ToString();

public MyCm()
{
InitializationComplete();
}

protected override void Dispose(bool disposing) { }

public override string UniqueId
{
get { return uniqueId; }
}

public void Stuff()
{
this.OnChanged(null);
}
}

Usage example:

        var cache = new MemoryCache("MyFancyCache");
var obj = new object();
var cm = new MyCm();
var cip = new CacheItemPolicy();
cip.ChangeMonitors.Add(cm);

cache.Set("MyFancyObj", obj, cip);

var o = cache.Get("MyFancyObj");
Console.WriteLine(o != null);

o = cache.Get("MyFancyObj");
Console.WriteLine(o != null);

cm.Stuff();

o = cache.Get("MyFancyObj");
Console.WriteLine(o != null);

o = cache.Get("MyFancyObj");
Console.WriteLine(o != null);

How do I clear a System.Runtime.Caching.MemoryCache

You should not call dispose on the Default member of the MemoryCache if you want to be able to use it anymore:

The state of the cache is set to indicate that the cache is disposed.
Any attempt to call public caching methods that change the state of
the cache, such as methods that add, remove, or retrieve cache
entries, might cause unexpected behavior. For example, if you call the
Set method after the cache is disposed, a no-op error occurs. If you
attempt to retrieve items from the cache, the Get method will always
return Nothing.
http://msdn.microsoft.com/en-us/library/system.runtime.caching.memorycache.dispose.aspx

About the Trim, it's supposed to work:

The Trim property first removes entries that have exceeded either an absolute or sliding expiration. Any callbacks that are registered
for items that are removed will be passed a removed reason of Expired.

If removing expired entries is insufficient to reach the specified trim percentage, additional entries will be removed from the cache
based on a least-recently used (LRU) algorithm until the requested
trim percentage is reached.

But two other users reported it doesnt work on same page so I guess you are stuck with Remove() http://msdn.microsoft.com/en-us/library/system.runtime.caching.memorycache.trim.aspx

Update
However I see no mention of it being singleton or otherwise unsafe to have multiple instances so you should be able to overwrite your reference.

But if you need to free the memory from the Default instance you will have to clear it manually or destroy it permanently via dispose (rendering it unusable).

Based on your question you could make your own singleton-imposing class returning a Memorycache you may internally dispose at will.. Being the nature of a cache :-)

Remove all items from MemoryCache

Avoid to use the default memory cache to have more control.
Create your own memory cache (by example as a static property of a static class) and when you need to erased it you can simply create a new one to replace the older one. Don't forget to call the dispose method.

It seems the way to go : How to clear MemoryCache?

Edit
When I read you code I'm not sure what you want to do.
If you want to remove a particular entry (which seems the case) you can use the remove method.

MemoryCache.Default.Remove($"DAL_CACHE_{HttpContext.Current?.User?.Identity?.Name}")

ASP.NET Core clear cache from IMemoryCache (set by Set method of CacheExtensions class)

Because I couldn't found any good solution I write my own.

In SamiAl90 solution (answer) I missed all properties from ICacheEntry interface.

Internally it uses IMemoryCache.

Use case is exactly the same with 2 additional features:

  1. Clear all items from memory cache
  2. Iterate through all key/value pairs

You have to register singleton:

serviceCollection.AddSingleton<IMyCache, MyMemoryCache>();

Use case:

public MyController(IMyCache cache)
{
this._cache = cache;
}

[HttpPut]
public IActionResult ClearCache()
{
this._cache.Clear();
return new JsonResult(true);
}

[HttpGet]
public IActionResult ListCache()
{
var result = this._cache.Select(t => new
{
Key = t.Key,
Value = t.Value
}).ToArray();
return new JsonResult(result);
}

Source:

public interface IMyCache : IEnumerable<KeyValuePair<object, object>>, IMemoryCache
{
/// <summary>
/// Clears all cache entries.
/// </summary>
void Clear();
}

public class MyMemoryCache : IMyCache
{
private readonly IMemoryCache _memoryCache;
private readonly ConcurrentDictionary<object, ICacheEntry> _cacheEntries = new ConcurrentDictionary<object, ICacheEntry>();

public MyMemoryCache(IMemoryCache memoryCache)
{
this._memoryCache = memoryCache;
}

public void Dispose()
{
this._memoryCache.Dispose();
}

private void PostEvictionCallback(object key, object value, EvictionReason reason, object state)
{
if (reason != EvictionReason.Replaced)
this._cacheEntries.TryRemove(key, out var _);
}

/// <inheritdoc cref="IMemoryCache.TryGetValue"/>
public bool TryGetValue(object key, out object value)
{
return this._memoryCache.TryGetValue(key, out value);
}

/// <summary>
/// Create or overwrite an entry in the cache and add key to Dictionary.
/// </summary>
/// <param name="key">An object identifying the entry.</param>
/// <returns>The newly created <see cref="T:Microsoft.Extensions.Caching.Memory.ICacheEntry" /> instance.</returns>
public ICacheEntry CreateEntry(object key)
{
var entry = this._memoryCache.CreateEntry(key);
entry.RegisterPostEvictionCallback(this.PostEvictionCallback);
this._cacheEntries.AddOrUpdate(key, entry, (o, cacheEntry) =>
{
cacheEntry.Value = entry;
return cacheEntry;
});
return entry;
}

/// <inheritdoc cref="IMemoryCache.Remove"/>
public void Remove(object key)
{
this._memoryCache.Remove(key);
}

/// <inheritdoc cref="IMyCache.Clear"/>
public void Clear()
{
foreach (var cacheEntry in this._cacheEntries.Keys.ToList())
this._memoryCache.Remove(cacheEntry);
}

public IEnumerator<KeyValuePair<object, object>> GetEnumerator()
{
return this._cacheEntries.Select(pair => new KeyValuePair<object, object>(pair.Key, pair.Value.Value)).GetEnumerator();
}

IEnumerator IEnumerable.GetEnumerator()
{
return this.GetEnumerator();
}

/// <summary>
/// Gets keys of all items in MemoryCache.
/// </summary>
public IEnumerator<object> Keys => this._cacheEntries.Keys.GetEnumerator();
}

public static class MyMemoryCacheExtensions
{
public static T Set<T>(this IMyCache cache, object key, T value)
{
var entry = cache.CreateEntry(key);
entry.Value = value;
entry.Dispose();

return value;
}

public static T Set<T>(this IMyCache cache, object key, T value, CacheItemPriority priority)
{
var entry = cache.CreateEntry(key);
entry.Priority = priority;
entry.Value = value;
entry.Dispose();

return value;
}

public static T Set<T>(this IMyCache cache, object key, T value, DateTimeOffset absoluteExpiration)
{
var entry = cache.CreateEntry(key);
entry.AbsoluteExpiration = absoluteExpiration;
entry.Value = value;
entry.Dispose();

return value;
}

public static T Set<T>(this IMyCache cache, object key, T value, TimeSpan absoluteExpirationRelativeToNow)
{
var entry = cache.CreateEntry(key);
entry.AbsoluteExpirationRelativeToNow = absoluteExpirationRelativeToNow;
entry.Value = value;
entry.Dispose();

return value;
}

public static T Set<T>(this IMyCache cache, object key, T value, MemoryCacheEntryOptions options)
{
using (var entry = cache.CreateEntry(key))
{
if (options != null)
entry.SetOptions(options);

entry.Value = value;
}

return value;
}

public static TItem GetOrCreate<TItem>(this IMyCache cache, object key, Func<ICacheEntry, TItem> factory)
{
if (!cache.TryGetValue(key, out var result))
{
var entry = cache.CreateEntry(key);
result = factory(entry);
entry.SetValue(result);
entry.Dispose();
}

return (TItem)result;
}

public static async Task<TItem> GetOrCreateAsync<TItem>(this IMyCache cache, object key, Func<ICacheEntry, Task<TItem>> factory)
{
if (!cache.TryGetValue(key, out object result))
{
var entry = cache.CreateEntry(key);
result = await factory(entry);
entry.SetValue(result);
entry.Dispose();
}

return (TItem)result;
}
}

Does an IIS Reset clear Memory Cache?

From my experiences and from peoples comments to back this up, it appears that it essentially does. The problem I was facing was actually an app pool not restarting properly, which lead to me thinking it hadn't cleared. It was actually an issue with the app pool.

How clear System.Runtime.Caching.MemoryCache of a running Windows service without stopping the service?

It sounds like your current cache using Enterprise Library has a file system dependency. You can do the same thing with MemoryCache by associating a HostFileChangeMonitor with each cache item. When the monitored file(s) change on disk, the cache items will be purged.



Related Topics



Leave a reply



Submit