Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

When using Cache.Add, is an exception thrown if the key exists already or does it fail silently?

I have read everywhere that the Add method fails if it already exists but does it throw an exception or does it fail silently?

I am writing a multithreaded web application where it should not exist already and it will cause problems if I overwrite the cache, so I can't use the Insert method.

Would this be something I could do:

try
{
    HttpContext.Current.Cache.Add("notifications", notifications, null,
      System.Web.Caching.Cache.NoAbsoluteExpiration, TimeSpan.FromHours(8),
      System.Web.Caching.CacheItemPriority.High, null);
}
catch
{
    //do whatever if notifications already exist
}

Thanks for any answers :)

like image 807
Base33 Avatar asked Dec 12 '22 00:12

Base33


1 Answers

System.Web.Caching.Cache is designed to be thread-safe in a multithreaded web application, and multiple threads may be in contention to add the same key to the cache. So it depends on how you want to handle such race conditions.

  • In many cases, you will be inserting immutable data into the cache and won't care which thread 'wins' the race. So you can use Add or Insert.

  • If you want "first one wins", use the Add method, if you want "last one wins (and overwrites)" use the Insert method.

  • There is no point in checking for existence before inserting/adding. Another thread may insert the item after your check and before you attempt to add/insert.

  • Neither Add nor Insert with throw an exception if the key already exists. It wouldn't make sense to do so as the Cache is designed for thread-safe insertion without locking. Add will fail silently, and Insert wil overwrite.

  • Incidentally, when reading from the Cache, don't check for existence then read:

    if (Cache["MyKey"] == null)
    {
        // ... handle missing value
    }
    else
    {
        // ... a race condition means the item may have been removed here
        // before you get a chance to read it
    
        MyType value = (MyType) Cache["MyKey"];
    }
    

    Instead, read the value from the cache and check for null:

    MyType value = Cache["MyKey"] as MyType; // for reference types
    if (value == null)
    {
        // ... handle missing value
    }
    
like image 80
Joe Avatar answered Mar 21 '23 12:03

Joe