Self-renewing MemoryCache

2019-05-23 01:07发布

I have implemented a cache that renews the containing values when they expire.

My code is this:

class MyCache
{
    private static readonly MemoryCache Cache = MemoryCache.Default;

    private CacheItemPolicy _errorpolicy;
    private CacheItemPolicy _warnPolicy;

    private CacheEntryRemovedCallback _warnCacheEntryRemovedCallback;
    private CacheEntryRemovedCallback _errorCacheEntryRemovedCallback;

    public void AddErrors(string key, object errors)
    {
        _errorCacheEntryRemovedCallback = ErrorItemRemovedCallback;
        _errorpolicy = new CacheItemPolicy
        {
            AbsoluteExpiration = DateTimeOffset.Now.AddSeconds(7.00),
            RemovedCallback = _errorCacheEntryRemovedCallback
        };

        Cache.Set(key, errors, _errorpolicy);
    }

    public void AddWarnings(string key, object warnings)
    {
        _warnCacheEntryRemovedCallback = WarningCacheItemRemovedCallback;
        _warnPolicy = new CacheItemPolicy
        {
            AbsoluteExpiration = DateTimeOffset.Now.AddSeconds(4.00),
            RemovedCallback = _warnCacheEntryRemovedCallback
        };

        Cache.Set(key, warnings, _warnPolicy);
    }

    private void ErrorItemRemovedCallback(CacheEntryRemovedArguments arguments)
    {
        Console.WriteLine("{0} Item removed: {1}", DateTime.UtcNow, arguments.CacheItem.Key);
        Cache.Set(arguments.CacheItem.Key, new List<string> { "error1", "error2", "error3" }, _errorpolicy);

    }

    private void WarningCacheItemRemovedCallback(CacheEntryRemovedArguments arguments)
    {
        Console.WriteLine("{0} Item removed: {1}", DateTime.UtcNow, arguments.CacheItem.Key);
        Cache.Set(arguments.CacheItem.Key, new List<string> { "warn1", "warn2", "warn3" }, _warnPolicy);
    }
}

But something is wrong.

The above writes this in the prompt:

04-05-2014 21:20:00 Item removed: warn
04-05-2014 21:20:00 Item removed: error
04-05-2014 21:20:20 Item removed: error
04-05-2014 21:20:20 Item removed: warn
04-05-2014 21:20:40 Item removed: warn
04-05-2014 21:20:40 Item removed: error
04-05-2014 21:20:40 Item removed: error
04-05-2014 21:20:40 Item removed: warn

... and I would have expected somnething like

04-05-2014 21:20:04 Item removed: warn
04-05-2014 21:20:07 Item removed: error
04-05-2014 21:20:08 Item removed: warn
04-05-2014 21:20:12 Item removed: warn
04-05-2014 21:20:14 Item removed: error
...

What am I missing?

Update 2014-05-14:

I have changed the field-level variables to local variables - but the same behaviour exists. Notice also that the sequence of removal from cache alters - first it is "errors-then-warns" - but next time it is "warns-then-errors".

Also notice that the first removal from cache is after 21 seconds - after this it happens constantly every 20 seconds.

14-05-2014 13:00:59 Adding errors to cache
14-05-2014 13:00:59 Adding warnings to cache
Press 'q' to quit
14-05-2014 13:01:20 Item removed: warn
14-05-2014 13:01:20 Item removed: error
14-05-2014 13:01:40 Item removed: error
14-05-2014 13:01:40 Item removed: warn
14-05-2014 13:02:00 Item removed: warn
14-05-2014 13:02:00 Item removed: error
14-05-2014 13:02:20 Item removed: error
14-05-2014 13:02:20 Item removed: warn
14-05-2014 13:02:40 Item removed: warn
14-05-2014 13:02:40 Item removed: error

My entire (new code) is here:

namespace DemoCache
{
    internal class Program
    {
        private static readonly List<string> ErrorList = new List<string> {"error1", "error2", "error3"};
        private static readonly List<string> WarningList = new List<string> {"warn1", "warn2", "warn3"};

        static void Main()
        {
            var myCache = new MyCache();

            Console.WriteLine("{0} Adding errors to cache ", DateTime.UtcNow);
            myCache.AddErrors("error", ErrorList);
            Console.WriteLine("{0} Adding warnings to cache", DateTime.UtcNow);
            myCache.AddWarnings("warn", WarningList);

            Console.WriteLine("Press 'q' to quit");

            var keepRunning = true;
            do
            {
                var key = Console.ReadKey(true);

                switch (Char.ToLower(key.KeyChar))
                {
                    case 'q':
                        keepRunning = false;
                        break;
                }
            } while (keepRunning);
        }
    }

    class MyCache
    {
        private static readonly MemoryCache Cache = new MemoryCache("name");

        //private CacheItemPolicy _errorpolicy;
        //private CacheItemPolicy _warnPolicy;

        //private CacheEntryRemovedCallback _warnCacheEntryRemovedCallback;
        //private CacheEntryRemovedCallback _errorCacheEntryRemovedCallback;

        public void AddErrors(string key, object errors)
        {
            CacheEntryRemovedCallback errorCacheEntryRemovedCallback = ErrorItemRemovedCallback;
            var errorpolicy = new CacheItemPolicy
            {
                AbsoluteExpiration = DateTime.Now.AddSeconds(7.00),
                RemovedCallback = errorCacheEntryRemovedCallback
            };

            Cache.Set(key, errors, errorpolicy);
        }

        public void AddWarnings(string key, object warnings)
        {
            CacheEntryRemovedCallback warnCacheEntryRemovedCallback = WarningCacheItemRemovedCallback;
            var warnPolicy = new CacheItemPolicy
            {
                AbsoluteExpiration = DateTime.Now.AddSeconds(11.00),
                RemovedCallback = warnCacheEntryRemovedCallback
            };

            Cache.Set(key, warnings, warnPolicy);
        }

        private void ErrorItemRemovedCallback(CacheEntryRemovedArguments arguments)
        {
            Console.WriteLine("{0} Item removed: {1}", DateTime.UtcNow, arguments.CacheItem.Key);
            AddErrors(arguments.CacheItem.Key, new List<string> { "error1", "error2", "error3" });
            //Cache.Set(arguments.CacheItem.Key, , _errorpolicy);

        }

        private void WarningCacheItemRemovedCallback(CacheEntryRemovedArguments arguments)
        {
            Console.WriteLine("{0} Item removed: {1}", DateTime.UtcNow, arguments.CacheItem.Key);
            AddWarnings(arguments.CacheItem.Key, new List<string> { "warn1", "warn2", "warn3" });
            //Cache.Set(arguments.CacheItem.Key, new List<string> { "warn1", "warn2", "warn3" }, _warnPolicy);
        }
    }
}

0条回答
登录 后发表回答