代码之家  ›  专栏  ›  技术社区  ›  Syed Saad

“System.ArgumentOutOfRangeException”的奇怪实例

  •  -3
  • Syed Saad  · 技术社区  · 6 年前

    我正在用一个线条系列从库中绘制图表 LiveCharts.Wpf 贝托·罗德里格斯。我正在将值发送到它所绘制的图表,并相应地进行更新。 我有一个seriescollection,可以根据计数器添加值,也可以删除一些值,例如:

    if (_counter > 2 )
    {
        SeriesCollection[3].Values[_counter-2] = double.NaN;   
    }
    

    所以如果计数器等于大于2的值,我将其设置为NaN,即从图表中删除一个点。

    问题是,在随机的时候,我得到一个 System.ArgumentOutOfRangeException 上面写着

    索引超出范围。必须为非负且小于集合的大小。

    在值被设置为 NaN 调试器显示计数器等于 0 是的。

    显然,当计数器等于或小于2时,我不允许执行此代码 if (_counter > 2 ) 条件,那么这个异常是如何在这个特定点上发生的呢?

    编辑:这个问题不是关于“System.ArgumentOutOfRangeException”是什么,正如在重复的问题中指出的,而是关于尽管事先检查了错误,但为什么会发生这个错误。基本上,由于多线程,计数器的值被设置为代码中其他地方的意外值,这是主要问题。seriescollection[3]与异常无关,如果有人这么认为,我建议从 LiveCharts 图书馆本身。

    2 回复  |  直到 6 年前
        1
  •  0
  •   Clemens    6 年前

    当然还有另一个线程可以改变 _counter 检查之间

    if (_counter > 2)
    

    把它用在

    Values[_counter - 2]
    

    更安全的实现只能访问一次:

    var i = _counter - 2;
    
    if (i >= 0)
    {
        SeriesCollection[3].Values[i] = double.NaN;
    }
    
        2
  •  2
  •   Zohar Peled    6 年前

    此代码在以下条件下引发索引超出范围异常:

    if (_counter > 2 )
    {
        SeriesCollection[3].Values[_counter-2] = double.NaN;   
    }
    
    1. SeriesCollection 少于4项。

    2. SeriesCollection[3].Values 少于 _counter-1 里面的东西。(因此,如果计数器为3,则 Values 集合必须至少有两个值-以便 _counter-2 将是第二项。

    另外,如果这是一个多线程环境,则很可能是另一个线程更改了 _counter 在条件和任务之间。为了防止这种情况,你需要使用 locks 以下内容:

    private object _lock = new Object(); 
    lock(_lock)
    {
        if (_counter > 2 )
        {
            SeriesCollection[3].Values[_counter-2] = double.NaN;   
        }
    }
    

    请注意,您的问题确实建议在多线程环境中工作-

    在将值设置为NaN且调试器显示计数器等于0的点上。

    只有当 _计数器 在条件评估和作业之间发生了变化。