c# - 从未插入的字典键中的空值

标签 c# dictionary

在下面的代码中,我插入了一些虚拟代码来检查 null 并删除它们只是为了尝试了解发生了什么。我仍然不明白为什么我的问题会发生 :)

我有以下将值插入字典的方法:

private Dictionary<string, DateTimeOffset> _keys = new Dictionary<string, DateTimeOffset>();
public async Task NotifyAsync(DateTimeOffset key)
{
    if (key==null)
    {
        this._logger.LogError("Recieved null key");
        return;
    }
    var dictKey = RadarContext.TrimTimeToPartitionBin(key, TimeSpan.FromMinutes(1));

    if (string.IsNullOrEmpty(dictKey))
    {
        this._logger.LogError("Recieved null dictKey for {time}",key);
        return;
    }

    _keys[dictKey] = key;
    await this.SetLastUpdatedAsync(DateTimeOffset.UtcNow);
}

没有其他插入。

然后我有以下循环键

foreach(var key in _keys.Keys.Where(k => string.IsNullOrEmpty( k )).ToArray())
{
    _logger.LogError("Removed null key: {time}",_keys[key]);
    _keys.Remove(key);
}

foreach (var key in _keys.Keys.OrderByDescending(key=> RadarContext.FromTrim(key,_logger)).Take(100).ToArray())
{
    if (_keys[key] < tminus1)
    {
        await actionblock.SendAsync(key);
    }
}

我的问题是我在 RadarContext.FromTrim

中得到一个空异常
public static DateTimeOffset FromTrim(string trim, ILogger  logger = null)
{
    try
    {
        var ticks = long.Parse(trim);
        return new DateTimeOffset(DateTimeOffset.MaxValue.UtcTicks - ticks, TimeSpan.Zero);
    }
    catch(Exception ex)
    {
        if (logger != null)
            logger.LogError(ex, "Failed to convert from {trim}", trim);

        throw;
    }
}

错误如下:

2019-03-05 23:15:21.922 +01:00 [ERR] Failed to convert from null
System.ArgumentNullException: Value cannot be null.
Parameter name: s
   at System.Int64.Parse(String s)
   at Ascend.Wammo.RadarIngestor.ServiceProvider.RadarContext.FromTrim(String trim, ILogger logger) in C:\dev\AscendXYZ\Ascend.Wammo.RadarIngestor\apps\Ascend.Wammo.RadarIngestor.ServiceProvider\RadarContext.cs:line 493

这里给定的代码怎么可能在循环 _keys.Keys.OrderByDescending(key=> RadarContext.FromTrim(key,_logger)) 时给 FromTrim 一个空值从未插入。

最佳答案

问题是您使用的是 Dictionary<TKey, TValue>来自多个线程,它不适合。据推测,一个线程中的内部状态的某些修改导致在另一个线程中看到空键。

ConcurrentDictionary<TKey, TValue> 旨在用于多线程 - 但我仍然会完全避免像您目前正在做的那样使用它。现在,您正在遍历键并分别查找每个键。我会循环遍历 条目:

var entries = _keys
    .OrderByDescending(entry => RadarContext.FromTrim(entry.Key, _logger))
    .Take(100)
    .ToArray();

foreach (var entry in entries)
{
    if (entry.Value < tminus1)
    {
        await actionblock.SendAsync(entry.Key);
    }
}

这样您就可以获得一致的快照。

关于c# - 从未插入的字典键中的空值,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55017697/

相关文章:

c# - switch 表达式中的多个语句 : C# 8

python - 不区分大小写的字典搜索?

python - 如何进行嵌套列表理解 (Python)

python - 将带有列表的字典添加到 Pandas DataFrame(pd.DataFrame(dict) vs df.append(dict))

android - 如何在Android map 上更改位置时删除标记并重新绘制它

c# - 使用 Dapper 映射 SqlGeography

c# - 错误 MSB3171 : Problem generating manifest

c# - SQL - 创建的数据库位置

c# - .net MemoryCache - 通知删除的项目

r - 如何正确链接极坐标投影图周围的跟踪点?