I have a private ConcurrentDictionary
that is a simple lookup table of some DB keys.
I'm trying to leverage the ConcurrentDictionary
so that it will only do one call to the db when 2+ requests to the same line of code, are made at the same time. (Which is why i'm using a ConcurrentDictionary
.)
How can I do this please?
This is what I was trying to do .. but I think it's storing the Task
in the dictionary ... not the result of the task....
private readonly ConcurrentDictionary<string, Task<int>> _myKeys = new ConcurrentDictionary<string, Task<int>>();
...
private async Task<int> DoStuffAsync(string key)
{
// do stuff here.
return await _myKeys.GetOrAdd(key,
async k => await _db.GetId(k)
.ConfigureAwait(false))
.ConfigureAwait(false);
}
Any ideas?
EDIT:
Notice my method signature and what I'm returning. Is it better to return an int
and not a Task<int>
and then somehow refactor my db call to still be async .. but .. better?
GetOrAdd
does not guarantee that the delegate will be called only once when it's called from multiple threads at the same time with the same value:This can be also seen in the implementation:
So, to do about as good a job as
GetOrAdd()
, you can do something like (input checking omitted):If the requirement to not call the delegate twice at the same time is just a performance optimization, this should be sufficient.
If it's required for correctness of your code, then even
GetOrAdd
is not sufficient and you will need to use additional synchronization.