diff --git a/src/libraries/Microsoft.Extensions.Caching.Memory/src/MemoryCache.cs b/src/libraries/Microsoft.Extensions.Caching.Memory/src/MemoryCache.cs index ef1f02a186766..fe972b6e50b66 100644 --- a/src/libraries/Microsoft.Extensions.Caching.Memory/src/MemoryCache.cs +++ b/src/libraries/Microsoft.Extensions.Caching.Memory/src/MemoryCache.cs @@ -23,8 +23,8 @@ public class MemoryCache : IMemoryCache internal readonly ILogger _logger; private readonly MemoryCacheOptions _options; - private readonly ConcurrentDictionary _entries; + private ConcurrentDictionary _entries; private long _cacheSize; private bool _disposed; private DateTimeOffset _lastExpirationScan; @@ -260,8 +260,8 @@ public bool TryGetValue(object key, out object result) public void Remove(object key) { ValidateCacheKey(key); - CheckDisposed(); + if (_entries.TryRemove(key, out CacheEntry entry)) { if (_options.SizeLimit.HasValue) @@ -281,7 +281,17 @@ public void Remove(object key) /// public void Clear() { + CheckDisposed(); + var oldEntries = Interlocked.Exchange(ref _entries, new ConcurrentDictionary()); + Interlocked.Exchange(ref _cacheSize, 0); + + foreach (var entry in oldEntries) + { + entry.Value.SetExpired(EvictionReason.Removed); + entry.Value.InvokeEvictionCallbacks(); + } + oldEntries.Clear(); } private void RemoveEntry(CacheEntry entry) @@ -325,7 +335,8 @@ private static void ScanForExpiredItems(MemoryCache cache) { DateTimeOffset now = cache._lastExpirationScan = cache._options.Clock.UtcNow; - foreach (KeyValuePair item in cache._entries) + var entries = cache._entries; // Clear() can update the reference in the meantime + foreach (KeyValuePair item in entries) { CacheEntry entry = item.Value; @@ -410,7 +421,8 @@ private void Compact(long removalSizeTarget, Func computeEntry // Sort items by expired & priority status DateTimeOffset now = _options.Clock.UtcNow; - foreach (KeyValuePair item in _entries) + var entries = _entries; // Clear() can update the reference in the meantime + foreach (KeyValuePair item in entries) { CacheEntry entry = item.Value; if (entry.CheckExpired(now))