I
I
Igor2015-04-17 14:22:59
WPF
Igor, 2015-04-17 14:22:59

Why does an "Unhandled exception of type 'System.ArgumentOutOfRangeException' in mscorlib.dll" occur?

Good afternoon
I have a WPF application. The window has a DataGrid and a TextBox.
There is a separate Connector class, it receives data, and as data is received, the contents of the DataGrid are updated. Data is received in a separate thread, which I launch like this:
new Thread(() => {...})..Start();
From this thread, when new data is received, I update the contents of the DataGrid:

Application.Current.Dispatcher.Invoke((ThreadStart)delegate { win.SetQuote(quote_list); });

As a result, the program runs from 1 to 10 seconds, each time in a different way, and crashes with a System.ArgumentOutOfRangeException error. The index is within the allowed range and does not exceed the size of the collection. It checked. While I was dealing with the problem, I added a TextBox to the application window and began to display the received data there - a text string. I do this in the same way as updating the DataGrid:
Application.Current.Dispatcher.Invoke((ThreadStart)delegate { win.SetLog(QuoteStr); });

I didn’t find the problem, but if it displays something like this in TexBox, then no error occurs, the application works, the DataGrid is updated.
Why does this happen? Why does an error occur if I do not display something in a TextBox and does not occur if something is displayed in a TextBox ? I have a suspicion that somehow I'm not updating the DataGrid correctly from another class and another thread, but I can't find an explanation.
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();
        }
    ...
    }
}

Answer the question

In order to leave comments, you need to log in

1 answer(s)
S
Sumor, 2015-04-17
@hurgadan

You are using in two different threads a List which is not thread safe. Most likely this is the problem. Either use thread-safe lists, such as ConcurrentQuery, or copy the entire list before passing it to win, such as using ToList() or ToArray().
Learn more about thread-safe collections

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question