126

ConcurrentDictionaryを使用するために、Dictionaryを使用してコードを書き直そうとしています。いくつかの例を確認しましたが、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

Func更新の場合にディクショナリに格納される値を返すaを渡す必要があります。あなたの場合(追加と更新を区別しないため)、これは次のようになります。

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 に答える