Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

MemoryCache empty just after adding an object

I'm facing a strange problem with ASP.NET MemoryCaching in a MVC 3 ASP.NET application.

Each time an action is executed, I check if its LoginInfo are actually stored in the MemoryCache (code has been simplified, but core is as follow):

[NonAction]
protected override void OnAuthorization(AuthorizationContext filterContext) {
  Boolean autorizzato = false;
  LoginInfo me = CacheUtils.GetLoginData(User.Identity.Name);
  if (me == null)
  {
    me = LoginData.UserLogin(User.Identity.Name);
    CacheUtils.SetLoginInfo(User.Identity.Name, me);
  }
  // Test if the object is really in the memory cache
  if (CacheUtils.GetLoginData(User.Identity.Name) == null) {
     throw new Exception("IMPOSSIBLE");
  } 
}

The GetLoginInfo is:

 public static LoginInfo GetLoginData(String Username)
        {
            LoginInfo local = null;
            ObjectCache cache = MemoryCache.Default;
            if (cache.Contains(Username.ToUpper()))
            {
                local = (LoginInfo)cache.Get(Username.ToUpper());
            }
            else
            {
                log.Warn("User " + Username + " not found  in cache");
            }
            return local;
        }

The SetLoginInfo is:

        public static void SetLoginInfo (String Username, LoginInfo Info)
        {
            ObjectCache cache = MemoryCache.Default;
            if ((Username != null) && (Info != null))
            {
                if (cache.Contains(Username.ToUpper()))
                {
                    cache.Remove(Username.ToUpper());
                }
                cache.Add(Username.ToUpper(), Info, new CacheItemPolicy());
            }
            else
            {
                log.Error("NotFound...");
            }
       }

The code is pretty straightforward, but sometimes (totally randomly), just after adding the LoginInfo to the MemoryCache, this results empty, the just added Object is not present, therefore I got the Exception.

I'm testing this both on Cassini and IIS 7, it seems not related to AppPool reusability (enabled in IIS 7), I've tested with several Caching policies, but cannot make it work

What Am I missing/Failing ?

PS: forgive me for my bad english

like image 291
BigMike Avatar asked Oct 21 '11 11:10

BigMike


People also ask

How do I reset my MemoryCache?

MemoryCache is a service so you can't dispose the cache. Simply remove the cached items you wish to remove. If you want to clear every item in cache then loop over the key and remove each item.

How does MemoryCache work C#?

In-Memory Cache is used for when you want to implement cache in a single process. When the process dies, the cache dies with it. If you're running the same process on several servers, you will have a separate cache for each server. Persistent in-process Cache is when you back up your cache outside of process memory.

Is .NET core MemoryCache thread safe?

The AddOrGetExisting method from the . NET Framework is thread-safe (according to the documentation).


3 Answers

Looking at the code for MemoryCache using a decomplier there is the following private function

private void OnUnhandledException(object sender, UnhandledExceptionEventArgs eventArgs)
{
  if (!eventArgs.IsTerminating)
    return;
  this.Dispose();
}

There is an unhandled exception handler setup by every MemoryCache for the current domain Thread.GetDomain() so if there is ever any exception in your application that is not caught which may be common in a website it disposes the MemoryCache for ever and cannot be reused this is especially relevant for IIS apps as apposed to windows applications that just exit on unhanded exceptions.

like image 195
JProgrammer Avatar answered Sep 27 '22 20:09

JProgrammer


The MemoryCache has limited size. For the Default instance, is't heuristic value (according to MSDN).

Have you tried to set Priority property on CacheItemPolicy instance to NotRemovable?

You can have race-condition because the Contains-Remove-Add sequence in SetLoginInfo is not atomic - try to use Set method instead.

Btw. you are working on web application so why not to use System.Web.Caching.Cache instead?

like image 23
Augi Avatar answered Sep 27 '22 20:09

Augi


I believe you are running into a problem that Scott Hanselman identified as a .NET 4 bug. Please see here: MemoryCache Empty : Returns null after being set

like image 36
James McCormack Avatar answered Sep 27 '22 20:09

James McCormack