126

我正在尝试使用 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? ***/);

任何指针将不胜感激。

4

4 回答 4

245

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

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

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

顺便说一句: MSDN 页面上有一个示例。

于 2011-08-11T18:37:06.313 回答
76

我希望,我没有错过您的问题中的任何内容,但是为什么不这样呢?它更容易、原子性和线程安全(见下文)。

userDic[authUser.UserId] = sessionId;

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

(见: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

于 2015-09-26T10:28:31.337 回答
32

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

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);
    }
}
于 2014-03-09T16:09:42.250 回答
1

对于那些感兴趣的人,我目前正在实施一个案例,这是使用“oldValue”即现有值而不是强制使用新值的一个很好的例子(我个人不喜欢“oldValue”这个词,因为它不是那个旧时它是在几个处理器滴答之前从并行线程中创建的)。

dictionaryCacheQueues.AddOrUpdate(
    uid,
    new ConcurrentQueue<T>(),
    (existingUid, existingValue) => existingValue
);
于 2014-03-28T12:45:45.890 回答