为ConcurrentDictionary AddOrUpdate中的更新部分添加什么

本文关键字:添加 什么 更新部 ConcurrentDictionary AddOrUpdate | 更新日期: 2023-09-27 18:05:22

我正在尝试使用Dictionary重写一些代码,以使用ConcurrentDictionary。我已经复习了一些例子,但在实现AddOrUpdate函数时仍然遇到问题。这是原始代码:

    dynamic a = HttpContext;
    Dictionary<int, string> userDic = this.HttpContext.Application["UserSessionList"] as Dictionary<int, String>;
   if (userDic != null)
   {
      if (useDic.ContainsKey(authUser.UserId))
      {
        userDic.Remove(authUser.UserId);
      }
   }
  else
  {
     userDic = new Dictionary<int,string>();
  }
  userDic.Add(authUser.UserId, a.Session.SessionID.ToString());
  this.HttpContext.Application["UserDic"] = userDic;

我不知道该为更新部分添加什么:

userDic.AddOrUpdate(authUser.UserId,
                    a.Session.SessionID.ToString(),
                    /*** what to add here? ***/);

任何建议都将不胜感激。

为ConcurrentDictionary AddOrUpdate中的更新部分添加什么

您需要传递一个Func,它在更新时返回要存储在字典中的值。我想在你的情况下(因为你不区分添加和更新(,这将是:

var sessionId = a.Session.SessionID.ToString();
userDic.AddOrUpdate(
  authUser.UserId,
  sessionId,
  (key, oldValue) => sessionId);

Func总是返回sessionId,因此Add和Update都设置了相同的值。

BTW:MSDN页面上有一个示例。

我希望我没有遗漏你的问题中的任何内容,但为什么不这样做呢?它更容易,原子和线程安全(见下文(。

userDic[authUser.UserId] = sessionId;

无条件地将键/值对存储到字典中,如果该键已经存在,则覆盖该键的任何值:使用索引器的setter

(请参见:http://blogs.msdn.com/b/pfxteam/archive/2010/01/08/9945809.aspx)

索引器也是原子的。如果你传递一个函数,它可能不是:

所有这些操作都是原子操作,并且相对于ConcurrentDictionary上的所有其他操作都是线程安全的。对于每个操作的原子性,唯一需要注意的是那些接受委托的操作,即AddOrUpdate和GetOrAdd。[…]这些委托在锁定之外调用

请参阅:http://blogs.msdn.com/b/pfxteam/archive/2010/01/08/9945809.aspx

我最终实现了一个扩展方法:

static class ExtensionMethods
{
    // Either Add or overwrite
    public static void AddOrUpdate<K, V>(this ConcurrentDictionary<K, V> dictionary, K key, V value)
    {
        dictionary.AddOrUpdate(key, value, (oldkey, oldvalue) => value);
    }
}

对于那些感兴趣的人来说,我目前正在实现一个案例,它是使用"oldValue"(即现有值(而不是强制使用新值的一个很好的例子(就我个人而言,我不喜欢"oldValue"这个词,因为它在几个处理器周期前从并行线程中创建时并没有那么旧(。

dictionaryCacheQueues.AddOrUpdate(
    uid,
    new ConcurrentQueue<T>(),
    (existingUid, existingValue) => existingValue
);

最简单的2023解决方案,无需引入额外的新变量:

userDic.AddOrUpdate(authUser.UserId,
                    a.Session.SessionID.ToString(),
                    (_, _) => a.Session.SessionID.ToString());

享受吧!

PS:了解MSDN上的丢弃变量。

相关文章: