'System.ArgumentOutOfRangeException'的C#奇怪实例

时间:2018-07-11 14:35:44

标签: c# wpf exception-handling livecharts

我正在使用LineSeries从Beto Rodriguez的库LiveCharts.Wpf中绘制图表。我正在将值发送到它绘制并相应更新的图表。 我有一个SeriesCollection,可以基于一个计数器添加值,也删除一些值,例如:

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

因此,如果计数器等于2以上,则将其值设置为NaN,即从图表中删除一个点。

问题是,在随机时间,我得到一个System.ArgumentOutOfRangeException并显示

  

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

将值设置为NaN时,调试器显示计数器等于0

很明显,在此if (_counter > 2 )条件下,当计数器等于或小于2时,我不允许执行此代码,那么在这个特定点怎么可能发生此异常?

编辑:此问题不是关于“ System.ArgumentOutOfRangeException”的问题,正如重复问题中指出的那样,而是关于尽管事先检查了该错误是怎么发生的。基本上,由于多线程处理,_counter的值在代码的其他位置被设置为意外值,这是主要问题。 SeriesCollection [3]与该异常无关,并且如果有人这样认为,我建议您从LiveCharts库本身检查该数据类型的实际含义。

2 个答案:

答案 0 :(得分:2)

在以下情况下,此代码将索引超出范围抛出异常:

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

  2. SeriesCollection[3].Values中的项目少于_counter-1。 (因此,如果counter为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。

只有在条件评估和赋值之间更改_counter的值时,这种情况才会发生。

答案 1 :(得分:0)

肯定有另一个线程在两次检查之间更改_counter的值

if (_counter > 2)

并在其中使用

Values[_counter - 2]

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

var i = _counter - 2;

if (i >= 0)
{
    SeriesCollection[3].Values[i] = double.NaN;
}