2

I've been researching how to implement basic memory caching in my class library. I came across this example and decided to implement something similar, but I've come across some problems:

  • Is MemoryCache really thread-safe? Sifting through the comments, I've found people saying it is and some people saying it isn't. I've never used this class before, so I'm not certain which comments apply to my situation.
  • If MemoryCache is not thread-safe, how does one make it thread-safe? Or should I be using something different for my situation?

In my case, consuming applications will have one instance of my class (DataProviderDecorator) used by 1-to-N threads. Will it be safe to use in that manner?:

public class DataProviderDecorator : IDataProvider
{
    private readonly IDataProvider Decoratee;
    private readonly MemoryCache Cache;                                         // System.Runtime.Caching.MemoryCache
    private ConcurrentDictionary<string, SemaphoreSlim> Locks { get; set; }     // System.Collections.Concurrent.ConcurrentDictionary and System.Threading.SemaphoreSlim

    public object GetItem(string key)
    {
        object result = null;

        if (Cache.Contains(key))
        {
            return Cache.Get(key);
        }

        SemaphoreSlim cacheLock = Locks.GetOrAdd(key, new SemaphoreSlim(1, 1));
        cacheLock.Wait();

        try
        {
            if (Cache.Contains(key))
            {
                return (QueryResult)Cache.Get(key);
            }

            result = Decoratee.GetItem(key);

            CacheItemPolicy cacheItemPolicy = new CacheItemPolicy();
            cacheItemPolicy.SlidingExpiration = new TimeSpan(0, 0, 30);
            if (!Cache.Add(key, result, cacheItemPolicy))
            {
                throw new Exception($"A record for the key [{key}] is already present in the cache.");
            }
        }
        finally
        {
            cacheLock.Release();
        }

        return result;
    }
}

Also, does anyone have any idea for how I should maintain the collection of locks? Presumably it would fill up indefinitely.

Max Jacob
  • 701
  • 1
  • 9
  • 20
  • no and what does google say, and usually its how you implement it, but off the bat last i checked its thread safe. first hit on google `https://stackoverflow.com/questions/20149796/memorycache-thread-safety-is-locking-necessary` – Seabizkit Aug 01 '19 at 14:58
  • Correct me if I'm wrong, but the [answer](https://stackoverflow.com/a/20150112/4396852) in that thread seems to be contradictory. The person says `MemoryCache` is thread-safe, but their [code](https://github.com/haneytron/dache/blob/master/Dache.CacheHost/Storage/MemCache.cs#L214) seems to be using **locks**. Also, the [other answer](https://stackoverflow.com/a/40089949/4396852) mentions threading issues related to the `Get` and `Contains` methods on `MemoryCache`. – Max Jacob Aug 01 '19 at 16:02

0 Answers0