Добрый день
Есть приложение 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();
}
...
}
}