Почему при вызове моего List <Point>.Clear () генерируется исключение ArgumentOutOfRangeException? - PullRequest
1 голос
/ 01 марта 2012

У меня есть List<Point>, который должен часто очищаться, поскольку значения используются один раз за итерацию, и я получаю ArgumentOutOfRangeException при вызове метода Clear().

Я прочиталОбъяснение, касающееся многопоточности, но, насколько я знаю, я не создал потоков (если только c # не выполняет какой-либо автоматический цикл for или while, но я сомневаюсь в этом).

Вот мой код:

List<Point> temp = new List<Point>();
List<Point> visited = new List<Point>();
// other initializations
for(int i = 0; i < points.Count;i++){
    if(temp.Count != 0)
        temp.Clear(); // Problem occurs here
    temp.Add(A);
    temp.Add(B);
    temp.Add(C);
    temp.Add(D);
    while(!(visited.Contains(temp[0]) && visited.Contains(temp[1])...){
        // calculate some stuff
        for(int j = 0; j <4;j++)
            visited.Add(temp[j]);
        // use point of interests
        temp.Clear();  // no issue on this clear
        temp.Add(newA);
        temp.Add(newB);
        temp.Add(newC);
        temp.Add(newD);
    }
    // display results
}

Выдает исключение ArgumentOutOfRangeException из первого temp.Clear() вызова.

Я также заметил, что если я очищаю список посещений в той же позиции, что и проблема temp.Clear(), я получаю ту же ошибку.

Мне кажется, что это проблема, связанная с C #, и, поскольку я очень плохо знаком с языком, мне интересно, не понимаю ли я что-то.

Ответы [ 6 ]

2 голосов
/ 01 марта 2012

Я думаю, что ваше исключение, когда вы пытаетесь получить доступ к вашим temp элементам, List.Clear () не выбрасывает ArgumentOutOfRangeException, потому что реализует сначала IList.Clear () и наконец ICollection.Clear () , и они просто выбрасывают NotSupportedException из .net2 до сих пор, а не ArgumentOutOfRangeException. Если вы вызываете ваш метод в разных потоках, я думаю, что ваша проблема в следующих строках:

    while(!(visited.Contains(temp[0]) && visted.Contains(temp[1])...){
    //calculate some stuff
    for(int j = 0; j <4;j++)
        visited.Add(temp[j]);

, и вы можете решить эту проблему, окружив эту часть в блоке lock.

Также лучше использовать visited.Intersect(temp).Count ==0 вместо вашего длинного условия if.

Редактировать: По вашему обновленному вопросу проблема ясна:

while (... (current! = Points [i + 1])) ooopps

когда i = n - 1, points[i + 1] находится вне диапазона.

1 голос
/ 01 марта 2012

points[i+1] выглядит неправильно в этом цикле whileif()). Ваш цикл переходит на points.Count, что на 1 больше наибольшего индекса. Ударить это будет ArgumentOutOfRangeException. (Если я что-то не замечаю.)

1 голос
/ 01 марта 2012

Примечание: в качестве ответа, а не комментария только потому, что это многословно - это не содержит решение проблемы

ОК, декомпилировав общий метод очистки списка, он выглядитнапример:

public void Clear()
{
    if (this._size > 0)
    {
        Array.Clear(this._items, 0, this._size);
        this._size = 0;
    }
    List`1 list`1s = this;
    list`1s._version = list`1s._version + 1;
}

Это потенциально не поточно-ориентированный (если this._size изменится с условия "if" на строку Array.Clear, то у вас может возникнуть проблема).Array.Clear сгенерирует исключение ArgumentOutOfRange, если вы предоставите неверные аргументы.См. http://msdn.microsoft.com/en-us/library/system.array.clear.aspx

Однако не может сделать так, чтобы List<T>.Clear мог быть таким хилым - так что вероятные ответы включают в себя: что-то в вашем коде либо играет с потоками, либо это не та строка

Таким образом, для дальнейшего продвижения вы можете пройти по коду и подтвердить его вызов Clear(), который вызывает ошибку - т.е. показать трассировку стека

1 голос
/ 01 марта 2012

Я склонен полагать, что ваш отладчик не синхронизирован, как упоминалось в других сообщениях

если это так, я склонен полагать, что ошибка находится на единственной строке, которую вы не указали нам полностью:

while(!(visited.Contains(temp[0]) && visited.Contains(temp[1])...){

имеет ли он доступ temp[0] ... temp[3] или temp[0] ... temp[4]

1 голос
/ 01 марта 2012

Я не перед ВС, однако вместо:

temp.Clear();

не могли бы вы попробовать:

temp = new List<Point>();

Вот пример кода, который я бросил вместе, и он прекрасно работает для меня:

        public void TestPoints()
        {
            List<Point> temp = new List<Point>();
            List<Point> visited = new List<Point>();
            List<Point> points = new List<Point>();
            points.Add(new Point(100, 100));
            points.Add(GeneratePoint());
            points.Add(GeneratePoint());
            points.Add(GeneratePoint());
            points.Add(GeneratePoint());


            //other initialization
            for (int i = 0; i < points.Count; i++)
            {
                if (temp.Count != 0)
                    temp.Clear(); //Problem occurs here
                temp.Add(GeneratePoint());
                temp.Add(GeneratePoint());
                temp.Add(GeneratePoint());
                temp.Add(GeneratePoint());
                while (!(visited.Contains(temp[0]) && visited.Contains(temp[1])))
                {
                    //calculate some stuff
                    for (int j = 0; j < 4; j++)
                        visited.Add(temp[j]);
                    //use point of interests
                    temp.Clear(); //no issue on this clear
                    temp.Add(GeneratePoint());
                    temp.Add(GeneratePoint());
                    temp.Add(GeneratePoint());
                    temp.Add(GeneratePoint());
                }
                //display results
            }
        }
        public Point GeneratePoint()
        {
            return new Point((new Random()).Next(1, 100), (new Random()).Next(1, 100));
        }

Как и предполагали другие, пытались ли вы «очистить» и «перестроить» свое решение.

Какая версия .NET? Это случайно не Моно?

0 голосов
/ 01 марта 2019

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

public static void RemoveAll<T>(this IList<T> collection)
{
    while (collection.Count > 0)
    {
        if (collection.Count == 1)
        {
            try
            {
                collection.RemoveAt(collection.Count - 1);
            }
            catch (ArgumentOutOfRangeException)
            {
                if (collection.Count > 0)
                    throw;
            }
        }
        else
            collection.RemoveAt(collection.Count - 1);
    }
}

// РЕДАКТИРОВАТЬ

Хорошо, теперь граф выдал то же исключение, поэтому я решил копать глубжеи найдено:

   w System.ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument argument, ExceptionResource resource)
   w Infragistics.FastItemDateTimeColumn.get_Item(Int32 index)
   w Infragistics.Controls.Charts.OrdinalTimeXAxis.UpdateActualRange()
   w Infragistics.Controls.Charts.OrdinalTimeXAxis.UpdateRangeOverride()
   w Infragistics.Controls.Charts.Axis.UpdateRange(Boolean immediate)
   w Infragistics.Controls.Charts.OrdinalTimeXAxis.OnFastItemsSourceEvent(FastItemsSourceEventArgs e)
   w Infragistics.Controls.Charts.CategoryAxisBase.HandleFastItemsSourceEvent(Object sender, FastItemsSourceEventArgs e)
   w System.EventHandler`1.Invoke(Object sender, TEventArgs e)
   w Infragistics.FastItemsSource.RaiseDataSourceEvent(FastItemsSourceEventAction action, Int32 position, Int32 count)
   w Infragistics.FastItemsSource.dataSourceRemove(Int32 position, IList oldItems)
   w Infragistics.FastItemsSource.OnItemsSourceEventProxyWeakCollectionChanged(IFastItemsSource fastItemsSource, Object sender, NotifyCollectionChangedEventArgs e)
   w Infragistics.FastItemsSource.<Attach>b__16_0(IFastItemsSource fastItemsSource, Object sender, NotifyCollectionChangedEventArgs e)
   w Infragistics.ItemSourceEventProxy.collectionChanged(Object sender, NotifyCollectionChangedEventArgs e)
   w System.Collections.Specialized.NotifyCollectionChangedEventHandler.Invoke(Object sender, NotifyCollectionChangedEventArgs e)
   w System.Collections.ObjectModel.ObservableCollection`1.OnCollectionChanged(NotifyCollectionChangedEventArgs e)
   w System.Collections.ObjectModel.ObservableCollection`1.RemoveItem(Int32 index)
   w System.Collections.ObjectModel.Collection`1.RemoveAt(Int32 index)
   w CryptoBot.Source.Common.Extensions.Extensions.RemoveAll[T](IList`1 collection) w G:\Moje Pliki\Programowanie\CSharp\Projects\CryptoBot\Cryptobot\CryptoBot\Source\Common\Extensions\Extensions.cs:wiersz 1035

Таким образом, в подобных сценариях коллекция, скорее всего, связана с чем-то, что использует некоторые асинхронные вызовы внутри.Есть ли у вас доступ к нему или нет.

...