在ConcurrentDictionary AddOrUpdate中为更新部分添加的内容

use*_*331 103 c# concurrent-collections

我试图使用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;
Run Code Online (Sandbox Code Playgroud)

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

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

任何指针将不胜感激.

M4N*_*M4N 210

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

var sessionId = a.Session.SessionID.ToString();
userDic.AddOrUpdate(
  authUser.UserId,
  sessionId,
  (key, oldValue) => sessionId);
Run Code Online (Sandbox Code Playgroud)

Func始终返回sessionId,以便Add和Update都设置相同的值.

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

  • 正如@NiklasPeter指出的那样(http://stackoverflow.com/a/32796165/8479),你最好只使用普通的索引器来覆盖这个值,因为在你的情况下你对现有值不感兴趣任何.更具可读性. (6认同)
  • 我正在努力争取找到一个函数来添加或更新到相同的值.thaks (4认同)
  • 好答案.只是从Visual Studio中显示的AddOrUpdate()的签名中,您只能猜测2个参数的含义.但是在特定情况下,@ user438331询问,我认为使用简单索引器的答案中的解决方案更好. (2认同)
  • 我建议在@NiklasPeter的回答中更改你的答案指向用户.这是一个更好的解决方案. (2认同)

Nik*_*ter 60

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

userDic[authUser.UserId] = sessionId;
Run Code Online (Sandbox Code Playgroud)

无条件地将键/值对存储到字典中,如果该键已存在,则覆盖该键的任何值:使用索引器的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

  • 是的原子性,因为它同时发生,不能一半发生或被中断。但是不安全,因为其他人可以在您执行之前将其更改为其他内容,在这种情况下,更改丢失,并且您不知道它发生了,如果您只想在值是您期望的情况下更改它,那么这不会为你做那个。 (3认同)

ste*_*ook 26

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

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

  • 为什么原来的实现没有这样的方法? (4认同)