kazuoua
kazuoua

Reputation: 313

Will System.Runtime.Caching.MemoryCache dispose IDisposable items when evicted?

I have a builder class that creates an instance implementing IDisposable. Whenever the item to build is already in the cache, the builder will return that instance instead. My question is, will the cache call the Dispose() method on the IDisposable items it contains when they are evicted or do I have to explicitly code that behavior on the callback CacheItemPolicy.RemovedCallback?

Upvotes: 10

Views: 3989

Answers (3)

Luke Vo
Luke Vo

Reputation: 20668

UPDATE: Do not use the code below for certificates and similar objects. Another thread may still be using this instance when it is disposed. See this question and answer for solution if that is the case.

To add to the other answers, if you use GetOrCreateAsync, use the ICacheEntry parameter to manually call Dispose. For example, I need to dispose X509Certificate2 for validating JWTs once my cache expires:

await cache.GetOrCreateAsync("IdTokenCerts", async entry =>
        {
            entry.AbsoluteExpirationRelativeToNow = JwtCertsCacheLifetime;
            entry.RegisterPostEvictionCallback((_, value, _, _) =>
            {
                if (value is X509SecurityKey key)
                {
                    key.Certificate.Dispose();
                }
            });

            // ...
        }

Upvotes: 0

Peter
Peter

Reputation: 173

I want to add to the accepted answer that you can let items be disposed on eviction if you want. Just call the Dispose() method in the RemovedCallback.

public class TestClass : IDisposable
{
    public void Dispose()
    {
        Console.WriteLine("disposed");
    }
}

MemoryCache _MemoryCache = new MemoryCache("TEST");

void Test()
{
    _MemoryCache.Add("key",
                      new TestClass(),
                      new CacheItemPolicy()
                      {
                          AbsoluteExpiration = DateTimeOffset.Now.AddSeconds(10),
                          RemovedCallback = (x) => { ((TestClass)x.CacheItem.Value).Dispose(); }
                      });

}

Upvotes: 2

I4V
I4V

Reputation: 35353

No Dispose is not called. It is easy to test.

public class TestClass : IDisposable
{
    public void Dispose()
    {
        Console.WriteLine("disposed");
    }
}

MemoryCache _MemoryCache = new MemoryCache("TEST");

void Test()
{
    _MemoryCache.Add("key",
                      new TestClass(),
                      new CacheItemPolicy()
                      {
                          AbsoluteExpiration = DateTimeOffset.Now.AddSeconds(10),
                          RemovedCallback = (_) => { Console.WriteLine("removed"); }
                      });

}

Upvotes: 11

Related Questions