使用Cache.Add时,如果密钥已存在或是否以静默方式失败,则抛出异常?

Bas*_*e33 4 c# asp.net caching

我已经在任何地方读过Add方法失败,如果它已经存在但它是否会抛出异常或者它是否会以静默方式失败?

我正在编写一个多线程的Web应用程序,它应该不存在,如果我覆盖缓存会导致问题,所以我不能使用Insert方法.

这是我能做的事情:

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
}
Run Code Online (Sandbox Code Playgroud)

谢谢你的回答:)

Joe*_*Joe 13

System.Web.Caching.Cache被设计为在多线程Web应用程序中是线程安全的,并且多个线程可能争用将相同的密钥添加到缓存.所以这取决于你想要如何处理这样的竞争条件.

  • 在许多情况下,您将向缓存中插入不可变数据,而不关心哪个线程"赢得"竞争.所以你可以使用AddInsert.

  • 如果你想要"第一个获胜",使用该Add方法,如果你想"最后一个获胜(和覆盖)"使用该Insert方法.

  • 在插入/添加之前检查是否存在没有意义.在您检查之后和尝试添加/插入之前,另一个线程可能会插入该项目.

  • 如果密钥已经存在,也Add不会Insert抛出异常.这样做是没有意义的,因为Cache是​​为没有锁定的线程安全插入而设计的. Add将无声地失败,并将Insert覆盖.

  • 顺便提一下,当从Cache中读取时,不检查是否存在然后阅读:

    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"];
    }
    
    Run Code Online (Sandbox Code Playgroud)

    而是从缓存中读取值并检查null:

    MyType value = Cache["MyKey"] as MyType; // for reference types
    if (value == null)
    {
        // ... handle missing value
    }
    
    Run Code Online (Sandbox Code Playgroud)