When using Cache.Add, is an exception thrown if th

2019-04-10 14:16发布

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 :)

3条回答
手持菜刀,她持情操
2楼-- · 2019-04-10 14:42

This is something that would be easy enough to test yourself, but it will throw an error. A good utility function to use:

    /// <summary>
    /// Places an item into the cache using absolute expiration.
    /// </summary>
    /// <param name="key">Key of the item being inserted</param>
    /// <param name="item">Item to insert</param>
    /// <param name="expireTime">Absolute expiration time of the item</param>
    public static void InsertIntoCacheAbsoluteExpiration(string key, object item, DateTime expireTime)
    {
        if (HttpContext.Current == null)
        {
            return;
        }

        lock (LOCK)
        {
            HttpRuntime.Cache.Remove(key);
            HttpRuntime.Cache.Add(
                key,
                item,
                null,
                expireTime,
                System.Web.Caching.Cache.NoSlidingExpiration,
                System.Web.Caching.CacheItemPriority.Normal,
                null);
        }
    }

Remove will not complain if the key doesn't exit. If you would like to test if the key is already there, you can always check

HttpRuntime.Cache.Get(key) != null

As long as you use a locking variable, you should not run into an issue where your check says something is NOT in the cache, and it shows up between the check and the add.

查看更多
小情绪 Triste *
3楼-- · 2019-04-10 14:43

It fails silently.

using System.Web;
using System.Web.Caching;

class Program
{
    static void Main(string[] args)
    {
        Cache cache = HttpRuntime.Cache;

        string object1 = "Object1";
        string object2 = "Object2";

        cache.Add(
            "Key", object1, null, Cache.NoAbsoluteExpiration, new TimeSpan(0, 10, 0), CacheItemPriority.Normal, null);
        cache.Add("Key", object2, null, Cache.NoAbsoluteExpiration, new TimeSpan(0, 10, 0), CacheItemPriority.Normal, null);

        string cachedstring = (string)cache.Get("Key");

        Console.WriteLine(cachedstring);

        Console.ReadLine();
    }
}

The output of this console app is Object1.

查看更多
来,给爷笑一个
4楼-- · 2019-04-10 15:00

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
    }
    
查看更多
登录 后发表回答