2017-10-31 9 views
-1

ConcurrentDictionaryを使用して、キャッシュされたデータを保持することを検討していますが、これは低速のソース(データベースなど)に由来します。.NET ConcurrentDictionaryのGetOrAddメソッドが非同期メソッドを呼び出すことはできますか?

データベースの呼び出しはasyncです。したがって、アイテムがディクショナリに存在しない場合は、同時ディクショナリコールで非同期メソッドを呼び出すことは可能ですか?例えば

const int userId = 1; 
var cachedUsers = new ConcurrentDictionary<int, Task<User>>(); 
var user = await cachedUsers.GetOrAdd(userId, val => GetSlowDbResultAsync(userId, cancellationToken)); 

ので、上記のやろうとしていることpseduoコードが言うあるもの:ユーザ#1はC-dictのです

  • 存在しませんか?
  • はい、それを使用してください。
  • いいえ、Dbのユーザー#1を取得し、キャッシュにスティックします。

だから、 - (キー/値のための)同時辞書の '価値' へTask<User>を置くことによって:

  • ことは大丈夫でしょうか?
  • は、私が上記の書いたコードを、この許容使用しないか、私は非同期/のawait/C#

ノートと神聖なものはすべて虐待を受けています

この質問はinspired from my question on twitterです。
これはprevious question I askedに似ていますが、それほど大きな牽引力はありませんでした。拡張メソッドについて

class Extension 
{ 
    public static User Get(this ConcurrentDictionary<int, User> conDict, int userID) 
    { 
     User user = null; 
     if (!conDict.TryGetValue(userID, out user)) 
     { 
      user = GetSlowDbResultAsync(userId, cancellationToken) 
      conDict.TryAdd(userID, user); 
     } 

     return user; 
    } 
} 

詳細は、このarticleにご確認ください:拡張メソッドを記述しようとすると、のようなものについてはどのように

+0

これをGetAsyncメソッドでラップして(クライアントが実装を理解する必要がないように)、うまくいくはずです。最初のヒットではデータベース呼び出しを待機し、2番目のヒットでは(同じユーザーIDの場合)、完了したタスクを待機します。それは私にとってはうまくいくようです。 – john

+1

なぜ「ConcurrentDictionary」を選択しましたか?物事をスピードアップすることを期待して非同期を使用していないことを願っています。 – CodingYoshi

+0

重複しているマークを参照してください。その答えはあなたが求めている技術とまったく同じです。コードの残りの部分がそれに対応するように書かれていると仮定すると、うまくいきます。 –

答えて

-2

+0

これはどのようにして質問に答えますか? – CodingYoshi

+0

@sean 2つのリクエストが同時にTryGetValueを実行するとどうなりますか、どちらもfalseを返します。.... :)次に、dbコールを2倍遅くしますか? –

関連する問題