2017-10-31 8 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 메서드로이를 마무리하면 (클라이언트가 구현을 이해할 필요가 없도록), 괜찮을 것이라고 생각합니다. 첫 번째 조회에서는 데이터베이스 호출을 기다리고 두 번째 조회 (동일한 사용자 ID의 경우)에서 완료된 태스크를 기다리게됩니다. 나에게 좋을 것 같다. – john

+1

왜 'ConcurrentDictionary'를 선택 했습니까? 당신이 비동기를 사용하지 않기를 바래요. – CodingYoshi

+0

중복 표시된 부분을 참조하십시오. 그 대답은 당신이 요구하는 기술을 정확하게 사용합니다. 코드의 나머지 부분이 그것을 수용하도록 작성되었다고 가정하면 잘 동작합니다. –

답변

-2

.

+0

이 질문에 어떻게 대답합니까? – CodingYoshi

+0

@sean 두 요청이 모두 TryGetValue를 동시에 수행하면 어떤 일이 발생합니까? 둘 다 false를 반환합니다 .... :) 그런 다음 2 배 느린 db 호출을 수행합니까? –