@hurgadan

Почему возникает исключение "Необработанное исключение типа «System.ArgumentOutOfRangeException» в mscorlib.dll"?

Добрый день
Есть приложение WPF. В окне есть DataGrid и TextBox.
Есть отдельный класс Connector, в нем идет получение данных и по мере получения данных, содержимое DataGrid обновляется. Получение данных идет в отдельном потоке, который запускаю так:
new Thread(() => {...})..Start();
Из этого потока при получении новых данных обновляю содержимое DataGrid:
Application.Current.Dispatcher.Invoke((ThreadStart)delegate { win.SetQuote(quote_list); });


В итоге программа работает от 1 до 10 секунд, каждый раз по разному, и вылетает с ошибкой System.ArgumentOutOfRangeException. При этом индекс находится в пределах диапазона допустимого, не превышает размера коллекции. Это проверял. Пока разбирался с проблемой, в окно приложения добавил TextBox и стал выводить туда получаемые данные - текстовую строку. Делаю это аналогично обновлению DataGrid:
Application.Current.Dispatcher.Invoke((ThreadStart)delegate { win.SetLog(QuoteStr); });


Проблему не нашел, но зато если выводит что-то таким вот образом в TexBox, то ошибки никакой не возникает, приложение работает, DataGrid обновляется.
Почему так проиcходит? Почему возникает ошибка если я не вывожу что-то в TextBox и не возникает, если что-то выводу в TextBox ? У меня подозрение, что я как-то не правильно обновляю DataGrid из другого класса и другого потока, но не могу найти объяснение.

using System;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Collections.Generic;
using System.Windows;
using System.Windows.Data;

using System.IO;
using System.IO.MemoryMappedFiles;

namespace UTox
{
    public class QuoteItem
    {
        public String Price { get; set; }
        public String Volume { get; set; }
    }

    class Connector
    {
        public volatile bool Run = true;
        private MainWindow win = (MainWindow)Application.Current.MainWindow;
        private List<QuoteItem> quote_list;
		
		...
		
        public Connector()
        {
            ...
            quote_list = new List<QuoteItem>();
			...
        }

        ...
		
        //Получает данные
        private void GettingQuoteData()
        {
            new Thread(() =>
            {
                string QuoteStr = "";
                string[] QuoteStrBid, QuoteStrParts;

                //Постоянный цикл в отдельном потоке
                while (Run)
                {
                    QuoteStr = GetTerminalQuoteData(); //Получает строчку из памяти
                    //Если данные есть
                    if (QuoteStr != "00" && QuoteStr != "" && QuoteStr != "0" && QuoteStr != "-1")
                    {
						//Если строчку ниже раскоментировать, то ошибка не возникает. Метод win.SetLog(QuoteStr) выводит строку QuoteStr в TexBox окна приложения
                        //Application.Current.Dispatcher.Invoke((ThreadStart)delegate { win.SetLog(QuoteStr); });
                        
						ClearTerminalQuoteData();//подтверждает что данные получены

                        //Разделяет снимок СТАКАНА на составляющие
                        QuoteStrParts = QuoteStr.Split('@');
                        QuoteStrBid = QuoteStrParts[0].Split(';');

						quote_list.Clear();

                        if (QuoteStrBid.Length > 9 )
                        {
                            int i = 9;
                            while (i > 0)
                            {
                                quote_list.Add(new QuoteItem() { Volume = QuoteStrBid[i - 1], Price = QuoteStrBid[i] });
                                i = i - 2;
                            }
                        }
						
						//Обновим содержимое DataGrid
                        Application.Current.Dispatcher.Invoke((ThreadStart)delegate { win.SetQuote(quote_list); });

                        QuoteStrParts = QuoteStrBid = null;

                    }
                    Thread.Sleep(100);
                }
            }).Start();
        }
		...
    }
}
  • Вопрос задан
  • 695 просмотров
Решения вопроса 1
@Sumor
Вы используетев двух разных потоках List который не является потокобезопасным. Скорее всего проблемы от этого. Нужно либо использовать потокобезопасные списки, например ConcurentQuery или перед передачей в win полностью копировать список, например, с помощью ToList() или ToArray().
Подробнее про потокобезопасные коллекции
Ответ написан
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы