C# Странный экземпляр исключения System.ArgumentOutOfRangeException

Я использую LineSeries для рисования диаграммы из библиотеки LiveCharts.Wpf Бето Родригеса. Я отправляю значения в диаграмму, которую она рисует и обновляет соответственно. У меня есть SeriesCollection, в которую я добавляю значения на основе счетчика, а также удаляю некоторые значения, например:

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

Поэтому, если значение счетчика больше 2, я устанавливаю значение NaN, то есть стираю точку с диаграммы.

Проблема в том, что в случайное время я получаю System.ArgumentOutOfRangeException, и он говорит

Index was out of range. Must be non-negative and less than the size of the collection.

в точке, где устанавливается значение NaN, и отладчик показывает, что счетчик равен 0.

Очевидно, я не разрешаю выполнять этот код, когда счетчик равен или меньше 2 по этому условию if (_counter > 2 ), так как же это исключение могло произойти в этой конкретной точке?

Обновлено: этот вопрос не о том, что такое «System.ArgumentOutOfRangeException», как указано в повторяющемся вопросе, а о том, как возникла эта ошибка, несмотря на ее предварительную проверку. В основном значение _counter устанавливается на неожиданное значение где-то еще в коде из-за многопоточности, и это была основная проблема. SeriesCollection [3] не имеет ничего общего с исключением, и если кто-то так считает, я предлагаю проверить, что на самом деле означает этот тип данных, из самой библиотеки LiveCharts.

Что ж, казалось бы, если _counter просто не представляет реальный размер массива Values .... Почему бы вам не проверить SerisCollection[3].Values.Length? (и даже это не будет потокобезопасным, если это имеет значение).

René Vogt 11.07.2018 16:39

Есть ли вероятность, что это проблема "Коллекция серий [3]"?

PaulF 11.07.2018 16:41

Если отладчик показывает, что _counter равен нулю, то я предполагаю, что ваша программа многопоточная, и другой поток обновил значение между вашим if и присвоением.

Hans Kilian 11.07.2018 16:41

Может быть, есть еще одна ветка, которая меняет _counter? Более безопасная реализация - var i = _counter - 2; if (i >= 0) { SeriesCollection[3].Values[i] = double.NaN; }.

Clemens 11.07.2018 16:41

@PaulF Я так не думаю, это обозначение LineSeries, у меня есть еще несколько SeriesCollection [x].

Syed Saad 11.07.2018 16:42

Проверьте значение _counter - 2, так как оно больше или равно длины вашей коллекции.

Kaitiff 11.07.2018 16:45

См. Мой комментарий об использовании временной переменной, уже сделанный Клеменсом - для отладки вы можете добавить условную точку останова внутри оператора if, чтобы проверить, иногда _counter равен нулю.

PaulF 11.07.2018 16:45

@Kensei, который не нужен, поскольку есть условие для проверки того, что, скорее всего, как указали Ганс Килиан или Клеменс, я проверю наличие дополнительных потоков, обращающихся к переменной _counter

Syed Saad 11.07.2018 16:49

Если SeriesCollection[3].Values не содержит значений, вы должны получить исключение ArgumentOutOfRangeException.

Zohar Peled 11.07.2018 16:52

Где устанавливается "_прилавок"? Есть ли причина, по которой вы используете переменную, а не «Значения.Длина» (или "Values.Count") напрямую?

PaulF 11.07.2018 16:56

@Clemens, пожалуйста, оставьте свой комментарий в качестве ответа, я бы принял его

Syed Saad 11.07.2018 17:18

@Liam это не так, см. Отредактированную версию. Я думаю, вы неправильно поняли, о чем идет речь.

Syed Saad 11.07.2018 17:40

Вы указываете в своей правке, что несмотря на то, что проверил его заранее. где вы это проверяете заранее? Как узнать, что SeriesCollection[3] содержит 3 значения или что SeriesCollection[3].Values[_counter-2] содержит значения Counter-2? Это должен быть дубликат, потому что единственный способ получить эту ошибку - это когда индекс выходит за пределы допустимого диапазона.

Liam 11.07.2018 17:55

Кажется, у вас может быть проблема синхронизации, но вы вообще не указываете это в вопросе?

Liam 11.07.2018 17:58

@Liam Я предлагаю вам изучить SeriesCollection, производный от LiveCharts.Helpers.NoisyCollection <ISeriesView>, который является членом LiveCharts. Во-первых, SeriesCollection [3] не имеет ничего общего с исключением, поскольку он просто обозначает номер строки, которую я рисую на Живом графике. У меня также есть набор SeriexCollection [x], каждый из которых рисует разные линии на моем графике. исключение было вызвано его «Values ​​[i]», где «i» было установлено на отрицательное число. Во-вторых, проверка выполняется «if (_counter> 2)», поэтому индекс в «Values ​​[_counter-2]» никогда не может быть отрицательным.

Syed Saad 11.07.2018 18:18
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
3
16
762
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Этот код генерирует исключение индекса вне диапазона при следующих условиях:

if (_counter > 2 )
{
    SeriesCollection[3].Values[_counter-2] = double.NaN;   
}
  1. В SeriesCollection меньше 4 элементов.

  2. SeriesCollection[3].Values содержит меньше, чем _counter-1 элементов. (поэтому, если счетчик равен 3, коллекция Values должна иметь как минимум два значения, чтобы _counter-2 был вторым элементом.

Кроме того, если это многопоточная среда, вполне возможно, что другой поток изменил значение _counter между условием и назначением. Чтобы этого не произошло, нужно использовать замки:

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

Обратите внимание, что ваш вопрос предполагает работу в многопоточной среде -

at the point where the value is being set to NaN and the debugger shows that the counter is equal to 0.

Это может произойти только в том случае, если значение _counter было изменено между оценкой условия и присвоением.

Я не согласен с тем, что «SeriesCollection содержит менее 4 элементов». , потому что это вообще не актуально, за исключением. Программа многопоточная, и, возможно, будет работать просто установка другой переменной, равной _counter, как указано в комментариях. Мне жаль, что я не упомянул, что программа многопоточная.

Syed Saad 11.07.2018 17:14

Я не говорю, что это вызвало исключение, я просто перечисляю это как возможную причину - однако предложение, которое я процитировал из вашего вопроса, а также ваш комментарий к моему ответу, предполагают, что проблема действительно связана с потоком безопасность. Добавьте замок, и все будет в порядке.

Zohar Peled 11.07.2018 17:17
Ответ принят как подходящий

Конечно, есть еще один поток, который изменяет значение _counter между проверками

if (_counter > 2)

и используя его в

Values[_counter - 2]

Более безопасная реализация будет обращаться к нему только один раз:

var i = _counter - 2;

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

Другие вопросы по теме