Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C# 4.0 MemoryCache - how to evict dependent cache entries when changes are made to their dependencies

I am attempting to evict entries from a MemoryCache when changes are made to other entries on which they are dependent. This is being set up by creating cache entry change monitors for the dependencies on the dependent keys:

public bool AddToCache(string key, object dataItem, 
    DateTimeOffset absoluteExpiration, IEnumerable<string> dependencyKeys)
{
    bool result = false;

    if (!string.IsNullOrWhiteSpace(key) && dataItem != null)
    {
        CacheItemPolicy policy = new CacheItemPolicy {
            AbsoluteExpiration = absoluteExpiration
        };

        if (masterKeys != null && masterKeys.Any())
        {
            policy.ChangeMonitors.Add(
                this.provider.Cache.
                    CreateCacheEntryChangeMonitor(dependencyKeys));

            foreach (ChangeMonitor monitor in policy.ChangeMonitors)
            {
                monitor.NotifyOnChanged(this.OnDependencyChanged);
            }
        }

        result = this.provider.Cache.Add(key, dataItem, policy);
    }

    return result;
}

The OnChangedCallBack method is this:

private void OnDependencyChanged(object state)
{
    // what do I do here as "state" is always null?
}

The items are added to the cache as intended, and the OnDependencyChanged method is called as expected when a change is made to a monitored key, however the "state" instance that is passed to it is always null which means that I know nothing about the cache key whose dependency has changed and can therefore not perform the planned eviction.

Have I missed something here, am I going about this all the wrong way?

like image 515
Jason Avatar asked Oct 12 '11 09:10

Jason


2 Answers

The delegate that is used as a parameter in OnChangedCacheEntry is:

public delegate void OnChangedCallback(object state);

So you have to call it like this:

monitor.NotifyOnChanged(delegate {
       OnChangedCacheEntry(OnDependencyChanged(dependencyKeys)); });

And then you will have access to the dependency keys in OnDependencyChanged

private void OnDependencyChanged(object state)
{
    IEnumerable<string> dependencyKeys = (IEnumerable<string>) state;
}
like image 113
radek Avatar answered Oct 12 '22 23:10

radek


I know it's an old thread, but here's what I have and it seems to work.

...

if (dependencies != null)
{
    var monitor = MemoryCache.Default.CreateCacheEntryChangeMonitor(dependencies);
    monitor.NotifyOnChanged(delegate { OnChangedCallback(dependencies); });
    policy.ChangeMonitors.Add(monitor);
}

...

private static void OnChangedCallback(object state)
{
    var keys = (IEnumerable<string>) state;
    if (keys != null)
        Logger.InfoFormat("callback - {0}", string.Join("|", keys.ToArray()));
    else
        Logger.InfoFormat("callback - null");
}

The dependencies parameter in OnChangedCallback(dependencies) is what's missing from original post.

like image 29
NCCHI Avatar answered Oct 12 '22 22:10

NCCHI