Модераторы: Partizan, gambit
  

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Проблема с потоками 
V
    Опции темы
ДобренькийПапаша
Дата 28.4.2010, 12:09 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1278
Регистрация: 14.1.2006
Где: г.Москва

Репутация: 3
Всего: 7



Решил всё-таки отдельную тему сделать, попробую сформулировать правильно.

Из функции по делегату в новом потоке вызывается функция парсинга текстового файла (выдираются значения для графика).
Код

  private void StartParsing(ParseCall parseFunc)
        {
            ParseCall parseCall = parseFunc;
            Thread chart = new Thread(parseCall.Invoke);
            chart.Start();
            
            //chart.Join();
            //for (int i = 0; i < this.x.Count; i++)
            //{
            //   currentChart.Series[0].Points.AddXY(x, this.high[i], this.low[i], this.open[i], this.close[i]);
            //}  
        }


Сам метод парсинга:
Код

private void ParseFileToStockChart()
        {
               //Тут куча работы по парсингу (которую я опустил) и, далее, собственно, прикручивание точек к графику
                if (currentChart.InvokeRequired)
                {
                    Invoke(new Action(() => currentChart.Series[0].Points.AddXY(DateTime.Parse(date), high, low, open, close)));
                } 
        }


Из-за того, что прикручивание находится в блоке InvokeRequired, то прикручивание происходит очень медленно, т.е. я некоторое время наблюдаю как точка за точкой появляются на графике...
Соответственно надо это вынести в основной поток, откуда был запуск, но если в функции StartParsing раскомментить строки, то почему-то, дальше chart.Join() выполнение не идёт (ждал долго, быть такого не может).

Короче, какой может быть выход из сложившейся ситуации?

Это сообщение отредактировал(а) ДобренькийПапаша - 28.4.2010, 12:10


--------------------
Меня зовут Себастьян Парейра, торговец чёрным деревом.
PM MAIL   Вверх
Miller_time
Дата 28.4.2010, 12:20 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 641
Регистрация: 8.9.2006
Где: Нижний Новгород

Репутация: нет
Всего: 1



А у тебя 

Код

currentChart


находиться в разных потоках? Может быть просто дожидаеться пока, один поток закончит, работы с обьектом и передаст управление другому обьекту. 


--------------------
Мы делаем игрыЗДЕСЬ
PM MAIL WWW ICQ   Вверх
ДобренькийПапаша
Дата 28.4.2010, 12:39 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1278
Регистрация: 14.1.2006
Где: г.Москва

Репутация: 3
Всего: 7



Цитата(Miller_time @ 28.4.2010,  12:20)
А у тебя 

Код

currentChart


находиться в разных потоках? Может быть просто дожидаеться пока, один поток закончит, работы с обьектом и передаст управление другому обьекту.

В разных потоках находится.  По поводу дождаться читайте выше.


--------------------
Меня зовут Себастьян Парейра, торговец чёрным деревом.
PM MAIL   Вверх
Heinzz
Дата 28.4.2010, 13:27 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 381
Регистрация: 12.12.2008
Где: .net

Репутация: 3
Всего: 9



а ежели Invoke не Required smile 


--------------------
user posted image
PM MAIL   Вверх
ДобренькийПапаша
Дата 28.4.2010, 13:59 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1278
Регистрация: 14.1.2006
Где: г.Москва

Репутация: 3
Всего: 7



Цитата(Heinzz @ 28.4.2010,  13:27)
а ежели Invoke не Required smile

Это вы к чему?

p.s. Пожалуйста, не пишите в тему, если не знаете как решить проблему.


--------------------
Меня зовут Себастьян Парейра, торговец чёрным деревом.
PM MAIL   Вверх
mrbrooks
Дата 28.4.2010, 14:46 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


трололомен
****


Профиль
Группа: Завсегдатай
Сообщений: 4259
Регистрация: 4.10.2006
Где: Дол Гулдур

Репутация: 17
Всего: 306



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

public void Run()
{
 //формируешь List<TROLOLO>data , где TROLOLO - есть сущность характеризующая данные взятые из файла. 
 Thread th = new Thread(WorkFunc);
 th.Start(data);
}

private void WorkFunc(object obj)
{
        List<TROLOLO>data = (List<TROLOLO>)obj;
        for(int i = 0; i<TROLOLO.Count;i++)
        {
                if (InvokeRequired)
                {
                    Invoke(new Action(() => currentChart.Series[0].Points.AddXY(DateTime.Parse(date), TROLOLO[i].high,...)));
                } 
                 else
                 {
                    currentChart.Series[0].Points.AddXY(DateTime.Parse(date), TROLOLO[i].high,...);
                 }
        }
}



зы. и в догонку что используете - MS Chart? Это реально важно - ибо здесь уже можно задействовать гораздо более эффективные способы вывода данных.

Это сообщение отредактировал(а) mrbrooks - 28.4.2010, 14:48
PM MAIL   Вверх
ДобренькийПапаша
Дата 28.4.2010, 19:17 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1278
Регистрация: 14.1.2006
Где: г.Москва

Репутация: 3
Всего: 7



Использую MSChart. Сейчас график наполняется точками в функции парсинга, это как вы сказали неудачно. Так и есть! Я же написал, что я в функции парсинга, запущенной в новом потоке мне приходится обращаться через InvokeReqiured к графику... что замедляет очень сильно наполнение графика точками. Я пытался сделать так, чтобы результаты парсинга присваивались коллекциям на уровне класса, чтобы прикрутить точки к графику уже в основном потоке, но какие я встретил проблемы я тоже описал выше...


--------------------
Меня зовут Себастьян Парейра, торговец чёрным деревом.
PM MAIL   Вверх
mrbrooks
Дата 28.4.2010, 23:01 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


трололомен
****


Профиль
Группа: Завсегдатай
Сообщений: 4259
Регистрация: 4.10.2006
Где: Дол Гулдур

Репутация: 17
Всего: 306



Ок. Я понимаю вашу озабоченность. Если вы используете M$ Chart - то используйте всю его мощь при работе с наборами данных. Продемонстрирую на примере:
Есть класс - характеризующий некую сущность - в моем случае координаты по Х и У:
Код

    public class ClassPoints
    {
        private int _x;
        private int _y;

        public int x
        {
            get { return _x; }
            set { _x = value; }
        }

        public int y
        {
            get { return _y; }
            set { _y = value; }
        }

        public ClassPoints(int x, int y)
        {
            this._x = x;
            this._y = y;
        }
    }


Тогда общее решение:
Код

        Random rand = new Random();
        BindingList<ClassPoints> list = new BindingList<ClassPoints>();

        private void Run()
        {
            for (int i = 0; i < 10000; i++) list.Add(new ClassPoints(i, rand.Next(1, 50))); //10000!!!!
            new Thread(WorkFunc).Start();
        }

        private void WorkFunc()
        {
            //Stopwatch sw = Stopwatch.StartNew();
            if (this.InvokeRequired) this.Invoke(new Action(() => BindingList2Chart()));
            else BindingList2Chart();
            //MessageBox.Show(sw.Elapsed.ToString());
        }

        private void BindingList2Chart()
        {
            chart1.DataSource = list;
            chart1.Series[0].XValueMember = "x";
            chart1.Series[0].YValueMembers = "y";
            chart1.DataBind();
        }


Данный код вывел 10000 точек менее чем за секунду (у меня есесно).

У меня складывается впечатлении что мы с вами уже этот вопрос обсуждали. Речь шла о парсинге CSV файла. Если это та же история я настоятельно рекомендую использовать все стандартные возможности для работы с файлом как с БД. Это быстрее и надежнее, чем строить по точкам и писать парсеры.
PM MAIL   Вверх
ДобренькийПапаша
Дата 29.4.2010, 07:55 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1278
Регистрация: 14.1.2006
Где: г.Москва

Репутация: 3
Всего: 7



Код

stockPoints.Add(new StockPoints(DateTime.Parse(date), high, low, open, close));
                
            if (currentChart.InvokeRequired)
            {
                Invoke(new Action(() =>
                {

                    currentChart.DataSource = stockPoints;
                    currentChart.DataBind();
                }));
            }
            else
            {
                currentChart.DataSource = stockPoints;
                currentChart.DataBind();
            }

Код

public class StockPoints
        {
            public DateTime X { get; private set; }
            public double High { get; private set; }
            public double Low { get; private set; }
            public double Open { get; private set; }
            public double Close { get; private set; }

            public StockPoints(DateTime x, double y1, double y2, double y3, double y4)
            {
                X = x;
                High = y1;
                Low = y2;
                Open = y3;
                Close = y4;
            }
        }
        BindingList<StockPoints> stockPoints = new BindingList<StockPoints>();

После завершения работы функции график остаётся белым. Посмотрел в отладчике, stockPoints имеет 80 точек как и должно быть, а вот после прохода функции currentChart.DataBind() currentChart.Series[0].Points.Count=0, т.е. привязка не произошла как я понимаю...

Это сообщение отредактировал(а) ДобренькийПапаша - 29.4.2010, 08:14


--------------------
Меня зовут Себастьян Парейра, торговец чёрным деревом.
PM MAIL   Вверх
ДобренькийПапаша
Дата 29.4.2010, 08:24 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1278
Регистрация: 14.1.2006
Где: г.Москва

Репутация: 3
Всего: 7



Код

if (currentChart.InvokeRequired)
            {
                Invoke(new Action(() => currentChart.Series[0].Points.DataBindXY(this.x, this.high, this.low, this.open, this.close)));
            }
            else
            {
                currentChart.Series[0].Points.DataBindXY(this.x, this.high, this.low, this.open, this.close);
                //currentChart.DataSource = stockPoints;
                //currentChart.DataBind();
            }


Так всё работает и очень быстро, спасибо mrbrooks за подсказу использовать binding.


--------------------
Меня зовут Себастьян Парейра, торговец чёрным деревом.
PM MAIL   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Прежде чем создать тему, посмотрите сюда:
Partizan
PashaPash

Используйте теги [code=csharp][/code] для подсветки кода. Используйтe чекбокс "транслит" если у Вас нет русских шрифтов.
Что делать если Вам помогли, но отблагодарить помощника плюсом в репутацию Вы не можете(не хватает сообщений)? Пишите сюда, или отправляйте репорт. Поставим :)
Так же не забывайте отмечать свой вопрос решенным, если он таковым является :)


Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, mr.DUDA, Partizan, PashaPash.

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | .NET для новичков | Следующая тема »


 




[ Время генерации скрипта: 0.0991 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.