Home Dashboard Directory Help
Search

MemoryCache class needs a Clear() method by admac


Status: 

Closed
 as Deferred Help for as Deferred


10
0
Sign in
to vote
Type: Bug
ID: 723620
Opened: 2/6/2012 5:06:52 AM
Access Restriction: Public
Moderator Decision: Sent to Engineering Team for consideration
2
Workaround(s)
view
0
User(s) can reproduce this bug

Description

The .NET 4 MemoryCache class in System.Runtime.Caching needs a Clear() method, to allow completely clearing the MemoryCache.Default cache. There is no such method.

You could get an enumerator and individually remove all keys, but the MSDN documentation says don't use the GetEnumerator method!


Details
Sign in to post a comment.
Posted by Microsoft on 12/4/2012 at 9:23 AM
Closing this bug for now. Product team will take a look at this suggestion for future release.
Posted by Microsoft on 2/8/2012 at 3:14 PM
Thank you for the suggestion. We're tracking this internally for a future release.
Posted by MS-Moderator08 [Feedback Moderator] on 2/6/2012 at 6:51 PM
Thank you for submitting feedback on Visual Studio 2010 and .NET Framework. Your issue has been routed to the appropriate VS development team for investigation. We will contact you if we require any additional information.
Posted by MS-Moderator01 on 2/6/2012 at 5:41 AM
Thank you for your feedback, we are currently reviewing the issue you have submitted. If this issue is urgent, please contact support directly(http://support.microsoft.com)
Sign in to post a workaround.
Posted by Thomas F. Abraham on 3/13/2014 at 12:04 PM
Here's an efficient way to clear the cache using the existing change monitoring infrastructure instead of enumeration. It also provides the flexibility to flush either the entire cache or a named subset.

// 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;
            SignaledChangeMonitor.Signaled += OnSignalRaised; // Register instance with the shared event
            base.InitializationComplete();
        }

        public static void Signal(string name = null)
        {
            if (Signaled != null)
            {
                Signaled(null, new SignaledChangeEventArgs(name)); // Raise shared event to notify all subscribers
            }
        }

        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("Instance " + _uniqueId + " notifying cache of change.", "SignaledChangeMonitor");
                base.OnChanged(null); // Cache objects obligated to remove the entry upon change notification.
            }
        }
    }

    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("DataKey" + idx.ToString(), "DataValue" + 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;
        }
    }
}
Posted by admac on 2/9/2012 at 12:52 AM
--Could write code such as the following as a workaround, but the MSDN documentation says not to use enumerators in production on MemoryCache as it is a blocking call

            List<string> cacheKeys = MemoryCache.Default.Select(kvp => kvp.Key).ToList();
            foreach (string cacheKey in cacheKeys)
                MemoryCache.Default.Remove(cacheKey);