c# - ContainsKey 为字符串返回 false

标签 c# .net

我基本上是在尝试将一些组织的 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/

相关文章:

c# - 当我使用 regasm 时,所有参数都输入为输入?那可以改变吗?

c# - 为什么我不能通过 Type.GetType() 找到我在 app.config 中引用的插件实例的类型?

c# - 将数据从 Html.Action 传递到局部 View

c# - 在不锁定文件的情况下加载程序集并保持正确的绑定(bind)上下文

javascript - 获取 .js 文件中的 .aspx 控件 ID

c# - 将表达式的值打印为字符串

c# - 为 ASP.NET MVC 项目设置数据访问的最佳方式是什么?

c# - SQL 语法错误

asp.net - 这些<% ... %>是什么?以及在页面中可以通过哪些方式使用它们

C# StreamReader 尝试/最终