C# 在ConcurrentDictionary AddOrUpdate中为更新部分添加什么

C# 在ConcurrentDictionary AddOrUpdate中为更新部分添加什么,c#,concurrent-collections,C#,Concurrent Collections,我正在尝试使用Dictionary重新编写一些代码以使用ConcurrentDictionary。我已经回顾了一些示例,但在实现AddOrUpdate函数时仍然遇到问题。这是原始代码: dynamic a = HttpContext; Dictionary<int, string> userDic = this.HttpContext.Application["UserSessionList"] as Dictionary<int, String>;

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

任何指针都将不胜感激。

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

var sessionId = a.Session.SessionID.ToString();
userDic.AddOrUpdate(
  authUser.UserId,
  sessionId,
  (key, oldValue) => sessionId);
也就是说,
Func
总是返回sessionId,以便Add和Update设置相同的值


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

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

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);
    }
}
静态类扩展方法
{
//添加或覆盖
公共静态void AddOrUpdate(此ConcurrentDictionary字典,K键,V值)
{
AddOrUpdate(key,value,(oldkey,oldvalue)=>value);
}
}

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

dictionaryCacheQueues.AddOrUpdate(
uid,
新建ConcurrentQueue(),
(existingUid,existingValue)=>existingValue
);

我希望,在你的问题中我没有遗漏任何东西,但为什么不这样做呢?它更简单、原子化和线程安全(见下文)

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

(见:)

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

所有这些操作都是原子操作,对于ConcurrentDictionary上的所有其他操作来说都是线程安全的。对每个操作的原子性的唯一警告是那些接受委托的操作,即AddOrUpdate和GetOrAdd。[…]这些委托在锁之外调用


请参阅:

我一直在努力寻找一个函数来添加或更新相同的值。他信回答得很好。仅从Visual Studio中显示的AddOrUpdate()的签名,您只能猜测这两个参数的含义。然而,在@user438331询问的特定情况下,我认为我的答案中使用简单索引器的解决方案更好。正如@niklapeter指出的(),您最好只使用普通索引器覆盖该值,因为在您的情况下,您对现有值(如果有的话)不感兴趣。更具可读性。我建议将您的答案改为指向@NiklasPeter's answer的用户。这是一个更好的解决方案。如果您不想更改现有值,您应该使用
GetOrAdd()
来代替。嗯,是的,您是对的,GetOrAdd()在本例中更简单且足够了-此提示的thx!是的,因为它同时发生,不能一半发生或被打断。然而,不安全的是,其他人可以在您更改之前将其更改为其他内容,在这种情况下,更改丢失了,并且您不知道它发生了,如果您只想在值符合您的期望时更改它,那么这不会对您产生影响。为什么原始实现没有这样的方法?
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);
    }
}
userDic[authUser.UserId] = sessionId;