我基本上是在尝试将一些组织的 ID 和名称缓存在字典中。我不断收到错误消息:Item with Same Key has already been added
。这对我来说很奇怪,因为第一个 if block 检查字典是否包含键,如果包含则退出该方法。
给出下面的(简化)代码,为什么我会收到错误?
public async Task<IList<Stat>> GetStats(DateTime start, DateTime end, string role, long tenantId)
{
...
var tasks = new List<Task>();
foreach (var org in query)
tasks.Add(GetOrgName(org));
await Task.WhenAll(tasks);
return query;
}
private Dictionary<string, string> Orgs = new Dictionary<string, string>();
private async Task GetOrgName(Organization org)
{
if (Orgs.ContainsKey(org.Id))
{
org.Name = Orgs[org.Id];
return;
}
var result = await _directoryService.GetOrganization(org.Id);
if (result != null)
org.Name = result.DisplayName;
else
org.Name = org.Id;
Orgs.Add(org.Id, org.Name);
}
最佳答案
所以问题是字典被多个任务同时访问。因此,当一个任务正在检查名称是否存在时,另一个任务正在添加它。此外,由于字典不是线程安全的,您当前的实现可能会遇到随机异常。
如果你改变这个:
var tasks = new List<Task>();
foreach (var org in query)
tasks.Add(GetOrgName(org))
到:
foreach (var org in query)
await GetOrgName(org);
你不会有那个问题。
另一种选择是为缓存使用线程安全集合。
但是,如果查询包含 1000 个项目,您的代码可能会对 _directoryService.GetOrganization
进行一千个并发调用。哪个可能是问题?
关于c# - ContainsKey 为字符串返回 false,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53808917/