我有一个private ConcurrentDictionary
,它是一些DB键的简单查找表。
我正在尝试利用ConcurrentDictionary
,这样当同一时间对同一行代码发出2次以上请求时,它只会对数据库进行一次调用。 (这就是我使用ConcurrentDictionary
的原因。)
我该怎么办呢?
这就是我尝试做的事情..但我认为它将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);
}
有什么想法吗?
编辑:
注意我的方法签名以及我要返回的内容。返回int
而不是Task<int>
然后以某种方式重构我的数据库调用仍然是异步的...但更好吗?
答案 0 :(得分:1)
如果您在不同的线程上同时调用GetOrAdd,可能会多次调用 addValueFactory ,但每次调用时,它的键/值对可能不会添加到字典中。
这也可以在the implementation中找到:
TValue resultingValue;
if (TryGetValue(key, out resultingValue))
{
return resultingValue;
}
TryAddInternal(key, valueFactory(key), false, true, out resultingValue);
return resultingValue;
所以,要做与GetOrAdd()
一样好的工作,你可以做一些事情(输入检查省略):
public static async Task<TValue> GetOrAddAsync<TKey, TValue>(
this ConcurrentDictionary<TKey, TValue> dictionary,
TKey key, Func<TKey, Task<TValue>> valueFactory)
{
TValue resultingValue;
if (dictionary.TryGetValue(key, out resultingValue))
{
return resultingValue;
}
return dictionary.GetOrAdd(key, await valueFactory(key));
}
如果不同时调用委托两次的要求只是性能优化,那就足够了。
如果您的代码正确无误,那么即使GetOrAdd
也不够,您还需要使用其他同步。