2

I am having a hard-time implementing the workaround to the problem with disposing Cache mentioned in this thread MemoryCache Empty : Returns null after being set.

My latest attempt has the following code to get an instance, wrapped as suggested, in a using statement to suppress the cache from being disposed:

private static CacheDl _instance;
public static CacheDl Instance
{
    get
    {
        if (_instance == null)
        {
            using (ExecutionContext.SuppressFlow())
            {
                _instance = new CacheDl();
            }
        }

        return _instance;
    }
}

private static ObjectCache Cache { get { return MemoryCache.Default; } }

Of course this doesn't work.. I have also tried wrapping the Cache 'getter' in something similar but still no deal.

I have also tried specifying a large pollingInterval to suppress the behavior altogether and still no success.

private ObjectCache _cache;
private ObjectCache Cache
{
    get
    {
        using (ExecutionContext.SuppressFlow())
        {
            return _cache ?? (_cache = new MemoryCache("my-cache", new NameValueCollection { { "pollingInterval", "30:00:00" } }));
        }
    }
}

You guessed it, no luck. Any help would be greatly appreciated.

By the way, I have already requested the mentioned Fixpack from Microsoft but not yet heard anything back after 4 hours having submitted the request..

Honestly, I would really prefer that this would be rolled up into an official Windows Update so we wouldn't have to hack around to get this working on non-.NET 4.5 systems.

Update: Specifically, I would like to know how I am meant to implement the recommended work-around. Can someone please show an example of how this can be implemented?

Community
  • 1
  • 1
atom.gregg
  • 987
  • 8
  • 14

2 Answers2

1

I am working on this same problem. In my case the problem seems to be the cache is disposed on the AppDomain's UnhandledException event. See the source snippet of MemoryCache here.

As you can see, it disposes itself. My solution is to wrap my cache access in a class that can subscribe to this event and initialize a new cache when the old one gets disposed. This solution seems to work for me but it does feel rather hack-y.

The cache will still be cleared unexpectedly on the UnhandledException event, but at least this way you are able to start over using a new cache.

public class MyCacheWrapper
{
    private MemoryCache cache;
    public MyCacheWrapper()
    {
        cache = new MemoryCache("settings");
        AppDomain.CurrentDomain.UnhandledException += (sender, args) =>
            {
                if(args.IsTerminating)
                    cache = new MemoryCache("settings");
            };
    }
}

Note also that you can also use this class to dispose and recreate the cache when you wish to clear it, because MemoryCache's Trim() method does not work properly.

Community
  • 1
  • 1
mao47
  • 967
  • 10
  • 25
  • Thanks for the answer, I ended up going with a long-polling configuration setting which avoided the internal disposal of the Cache. I had tried to apply the setting in code which didn't work for whatever reason, but setting the values in configuration solved the issue and I haven't had any 'disposed' Cache problems for a week now. – atom.gregg Jul 02 '13 at 07:06
  • Thanks, I later found out that the reason mine was getting disposed in the first place was due to a improper configuration in my development environment, but due to that and other problems, plus just to be safe in case some other error caused the disposal, I ended up just changing it to use System.Web.Caching.Cache. – mao47 Jul 02 '13 at 18:45
0

Ended up sorting this out with configuration settings to extend the Cache polling interval sufficient enough that the application pool will recycle before the interval is reached. Had tried doing this in code when constructing a Cache instance but that didn't work out..

A comment on the relevant Connect issue mentions this as workable hack if you can control your application pool, while another mentions this on the social.msdn forum.

Connect Issue

social.msdn

The configuration setting which increases the polling interval by 30 hours:

<system.runtime.caching>
    <memoryCache>
        <namedCaches>
            <add name="Default"
                cacheMemoryLimitMegabytes="0"
                physicalMemoryLimitPercentage="0"
                pollingInterval="30:00:00" />
        </namedCaches>
    </memoryCache>
</system.runtime.caching>
atom.gregg
  • 987
  • 8
  • 14