powered by simpleCommunicator - 2.0.49     © 2025 Programmizd 02
Форумы / WPF, Silverlight [игнор отключен] [закрыт для гостей] / Асинхронная загрузка данных в Chart
42 сообщений из 42, показаны все 2 страниц
Асинхронная загрузка данных в Chart
    #39640803
Фотография mraklbrw
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Добрый день.

Такая ситация: есть окно - на нём создаётся пользовательский контрол (Grid, Chart, Button-ы).
В конструкторе этого контрола вызывается функция, которая подгружает данные в Chart.
Происходит это синхронно и не очень быстро => окно приложения зависает.
Из другого потока не получается: доступ к UI-элементу не из STA-потока-ошибка.

Я попробовал так:
Код: c#
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
      {
	  
	  // Окно приложения - MainWindow

	  ADC adelc = AddChart; // AddChart - функция, в которой создаётся контрол
            AsyncCallback cb = new AsyncCallback(MyAsyncCallback);
            IAsyncResult ar = adelc.BeginInvoke("SBER", cb, adelc);


        }

        public void MyAsyncCallback(IAsyncResult ar)
        {
            string s;
            int iExecThread;

            // Because you passed your original delegate in the asyncState parameter
            // of the Begin call, you can get it back here to complete the call.
            ADC dlgt = (ADC)ar.AsyncState;

            // Complete the call.
            dlgt.EndInvoke(ar);
        }

        delegate void ADC(object o);
		
		


И опять же - Вызывающим потоком должен быть STA.
Если просто Dispatcher.BeginInvoke - то выполняется не асинхронно.

Код: c#
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
{

// Окно MainWindow

ADC adelc = AddChart;
          
            IAsyncResult ar = adelc.BeginInvoke("SBER", MyAsyncCallback, "");




        }

        public void MyAsyncCallback(IAsyncResult ar)
        {
            MessageBox.Show("kk");
        }

        delegate void ADC(object o);


И - вызывающим потоком должен быть STA.
...
Рейтинг: 0 / 0
Асинхронная загрузка данных в Chart
    #39640804
Фотография Shocker.Pro
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
mraklbrwПроисходит это синхронно и не очень быстро => окно приложения зависает.
Из другого потока не получается: доступ к UI-элементу не из STA-потока-ошибка.Стандартный подход - получить данные асинхронно в DTO (долгая операция), затем быстро перегрузить в UI-контролы в потоке UI.
...
Рейтинг: 0 / 0
Асинхронная загрузка данных в Chart
    #39640806
Фотография Shocker.Pro
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Либо воспользоваться паттерном MVVM - загрузить данные в модель представления, а представление само заберет изменения в нужном потоке
...
Рейтинг: 0 / 0
Асинхронная загрузка данных в Chart
    #39640815
Фотография Petro123
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Третий вариант - разберитесь почему данные к графику не готовы. Они не должны вычислятся. Это статистика уже прошедших событий.
...
Рейтинг: 0 / 0
Асинхронная загрузка данных в Chart
    #39640818
Фотография mraklbrw
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Данные не вычисляются.
Они добавляются на соответствующие области графика.
...
Рейтинг: 0 / 0
Асинхронная загрузка данных в Chart
    #39640820
Фотография mraklbrw
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Что такое DTO?
...
Рейтинг: 0 / 0
Асинхронная загрузка данных в Chart
    #39640822
Фотография Petro123
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
mraklbrwДанные не вычисляются.
Они добавляются на соответствующие области графика.вопрос был почему долго.
Какая разница добавляются или вытягиваются?
...
Рейтинг: 0 / 0
Асинхронная загрузка данных в Chart
    #39640824
Фотография Shocker.Pro
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
...
Рейтинг: 0 / 0
Асинхронная загрузка данных в Chart
    #39640825
Фотография Shocker.Pro
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
...
Рейтинг: 0 / 0
Асинхронная загрузка данных в Chart
    #39640826
Фотография Shocker.Pro
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
mraklbrwфункция, которая подгружает данные в Chart.надо разделить наmraklbrwфункция, которая подгружаетиmraklbrwданные в Chart.
...
Рейтинг: 0 / 0
Асинхронная загрузка данных в Chart
    #39640895
Фотография mraklbrw
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Попробовал так:

Код: c#
1.
2.
3.
4.
5.
6.
7.
8.
9.
async void VeryLongMethod()
        {
            string access = await AddChart("SBER2");
        }

async Task<string> AddChart(object o)
        {
            // Загрузка контрола
        }


И вызываю функцию VeryLongMethod().

Выполняется не асинхронно.
...
Рейтинг: 0 / 0
Асинхронная загрузка данных в Chart
    #39640898
Фотография Shocker.Pro
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
mraklbrwИ вызываю функцию VeryLongMethod().

Выполняется не асинхронно.выполняется асинхронно, но не ждет окончания задачи, ибо async void. Вы бы почитали что-нить про работу с многопоточностью.

А что касается задачи - еще раз.
ДЛИТЕЛЬНУЮ операцию получения данных (что у вас там, загрузка из БД, загрузка из интернета и т.п.) нужно выполнить асинхронно (и не через async void) и сложить эти данные в DTO. А также произвести все манипуляции над ними.

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

Тогда тормозов не будет
...
Рейтинг: 0 / 0
Асинхронная загрузка данных в Chart
    #39640900
Фотография Petro123
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
mraklbrwПопробовал так:
это монолог а не диалог.
- почему у меня 1000 строк показываются быстро в таблице. А у вас медленно?
На вопросы не отвечаете?
...
Рейтинг: 0 / 0
Асинхронная загрузка данных в Chart
    #39640902
Фотография Shocker.Pro
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
mraklbrwВ конструкторе этого контрола вызывается функция, которая подгружает данные в Chart.констуктор (а вообще это неверный подход) пусть принимает на вход данные, а не загружает их сам. А по хорошему, все данные контрол должен получить через свойства, а конструктор - быть без параметров
...
Рейтинг: 0 / 0
Асинхронная загрузка данных в Chart
    #39640909
Фотография mraklbrw
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
В конструкторе контрола почти ничего не делается.
Создание контрола занимает примерно до 3 сек (тоже много, да).
После этого вызывается функция констрола SetQuotes, в которой уже в Chart добавляются свечи из уже готового HashSet<Candle>, т.е. данные готовы - в течении 15 секунд они (6000 свеч примерно) загружаются в Chart.

Код: c#
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
            candleSeries = new Series("SeriesCandle")
            {
                ChartType = SeriesChartType.Candlestick, // Тип - японские свечи
                YAxisType = AxisType.Secondary,
                ChartArea = "ChartAreaCandle",
                ShadowOffset = 2,
                YValuesPerPoint = 4
            };

            _chartForCandle.Series.Add(candleSeries);

            for (int i = 0; i < quotes.Count; i++)
            {
                // Добавление свечи
                candleSeries.Points.AddXY(i, quotes.ElementAt(i).Low, quotes.ElementAt(i).High, quotes.ElementAt(i).Open, quotes.ElementAt(i).Close);
                // Добавление подписи-времени
                candleSeries.Points[candleSeries.Points.Count - 1].AxisLabel = quotes.ElementAt(i).Date.ToString(CultureInfo.InvariantCulture);
                // Назначение цветов свечей
                if (quotes.ElementAt(i).IsPositive) candleSeries.Points[candleSeries.Points.Count - 1].Color = System.Drawing.Color.FromName(Program_Settings.PositiveCandleColor);
                else candleSeries.Points[candleSeries.Points.Count - 1].Color = System.Drawing.Color.FromName(Program_Settings.NegativeCandleColor);
            }



Т.е. вот этот цикл и занимает кучу времени.
...
Рейтинг: 0 / 0
Асинхронная загрузка данных в Chart
    #39640911
Фотография Shocker.Pro
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Ужас!
mraklbrw
Код: c#
1.
quotes.ElementAt(i)

нафига тут ElementAt?
...
Рейтинг: 0 / 0
Асинхронная загрузка данных в Chart
    #39640912
Фотография mraklbrw
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
HashSet<Candle> - quotes[i] - так обратиться нельзя.
...
Рейтинг: 0 / 0
Асинхронная загрузка данных в Chart
    #39640913
Фотография Petro123
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
mraklbrw6000 свеч примерно
дайте скрин свой или похожий из гугла.
По 5 свечей на пиксель?
...
Рейтинг: 0 / 0
Асинхронная загрузка данных в Chart
    #39640914
Фотография Shocker.Pro
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Почитайте, что такое Enumerator, как работает Linq и т.п.
У вас проход по массиву quotes при 6000 элементах будет выполнен 6*6000 раз
замените for на foreach
немедленно!
и никогда так больше не делайте!
...
Рейтинг: 0 / 0
Асинхронная загрузка данных в Chart
    #39640915
Фотография Shocker.Pro
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
mraklbrwHashSet<Candle> - quotes[i] - так обратиться нельзя.потому что вообще не надо к нему обращаться.
...
Рейтинг: 0 / 0
Асинхронная загрузка данных в Chart
    #39640918
Фотография mraklbrw
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
...
Рейтинг: 0 / 0
Асинхронная загрузка данных в Chart
    #39640919
Фотография Shocker.Pro
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Далее - вот это тутmraklbrw
Код: c#
1.
candleSeries.Points[candleSeries.Points.Count - 1]

нафига несколько раз? Что мешает сначала подготовить точку, а потом выполнять AddXY?

И вообще, нельзя ли подготовить массив точек заранее (асинхронно), а потом присвоить его candleSeries.Points? (тут я не знаю, позволит ли это сделать чарт, но это было бы логично)
...
Рейтинг: 0 / 0
Асинхронная загрузка данных в Chart
    #39640921
Фотография mraklbrw
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Shocker.ProПочитайте, что такое Enumerator, как работает Linq и т.п.
У вас проход по массиву quotes при 6000 элементах будет выполнен 6*6000 раз
замените for на foreach
немедленно!
и никогда так больше не делайте!

Исправил, выполнение данного участка кода ~ 1-1.5 сек.
Понял ошибку, действительно, было очень глупо, буду дальше смотреть.
...
Рейтинг: 0 / 0
Асинхронная загрузка данных в Chart
    #39640923
Фотография Petro123
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
mraklbrw1-1.5 сек.
Тогда, я так понял, топик решён.
Удачи!
...
Рейтинг: 0 / 0
Асинхронная загрузка данных в Chart
    #39640925
Фотография Shocker.Pro
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Shocker.ProИ вообще, нельзя ли подготовить массив точек заранее (асинхронно), а потом присвоить его candleSeries.Points? (тут я не знаю, позволит ли это сделать чарт, но это было бы логично)Но даже если не позволит присвоить массив точек, все равно логично подготовить сначала массив точек вне конструктора, а в конструкторе его только добавить. Это то, о чем я твержу вам с самого начала - не надо получать данные внутри конструктора, надо их сначала подготовить, а потом грузить в контрол
...
Рейтинг: 0 / 0
Асинхронная загрузка данных в Chart
    #39640935
Фотография mraklbrw
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
В конструкторе почти ничего нет.

Код: c#
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
private void AddChart(string quoteCode)
        {
            HashSet<Candle> quotes = null;

                if (!File.Exists("Quotes/" + quoteCode + "_M15.txt"))
                    TimeframesQuotesGenerator.GenerateTimeframeFile(quoteCode, TimeframesQuotesGenerator.Timeframe.m15);

                if (quotes == null)
                    quotes = QuotesStorage.ReadQuotes(quoteCode + "_M15");

            ChartGrid chartG1 = new ChartGrid();
                chartG1.QuoteCode = quoteCode;
                chartG1.Name = quoteCode + "Chart";
                chartG1.Width = Program_Settings.ChartWidth;
                chartG1.Height = Program_Settings.ChartHeight;
                chartG1.wfh.Width = chartG1.Width;
                chartG1.Height = chartG1.Height - 30;

                MainGrid.Children.Add(chartG1);

                chartG1.SetQuotes(quotes); // M15 quotes
                                           //chartG1.AddIndicator(ChartGrid.LowAreaIndicator.Volume);
                                           //chartG1.AddIndicator(ChartGrid.MainAreaIndicator.MovingAverage);
        }



До вызова chartG1.SetQuotes(quotes) всё выполняется почти мгновенно (хотя да, есть считывание котировок с файла).
Но мы же не можем грузить котировки по всем доступным инструментам предварительно в память?
chartG1.SetQuotes(quotes) - занимает несколько секунд в совокупности.
Тут добавляются точки на график, рассчитываеются min, max - корректирование визуального отображения графика.
...
Рейтинг: 0 / 0
Асинхронная загрузка данных в Chart
    #39640938
Фотография Shocker.Pro
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Конструктор вы не показываете, ладно, фиг с ним.
SetQuotes вы показали лишь частично. Если в остальном такой же говнокод, как в случае с ElementAt, то неудивительно.
Коллекцию точек с большой вероятностью, можно подготовить заранее, вне SetQuotes и вне UI-потока
...
Рейтинг: 0 / 0
Асинхронная загрузка данных в Chart
    #39640943
Фотография mraklbrw
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
И всё-таки, пробую сделать асинхронным подготовку контрола.

Код: c#
1.
2.
3.
4.
void gg()
        {
            this.Dispatcher.BeginInvoke(new Action(() => { AddChart("SBER2"); }) );
        }



Вызываю:
Код: c#
1.
2.
Thread t1 = new Thread(gg);
            t1.Start();



Окно появляется быстро, но зависает, пока выполяется функция AddChart().
...
Рейтинг: 0 / 0
Асинхронная загрузка данных в Chart
    #39640944
Фотография mraklbrw
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Код: c#
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
66.
67.
68.
69.
70.
71.
72.
73.
74.
75.
76.
77.
78.
79.
public void SetQuotes(HashSet<Candle> quotes)
        {
                this.quotes = quotes; // M15 quotes

                Thread t1 = new Thread(QuotesChecker); // Проверка - рассчитаны ли другие таймфреймы, кроме M15
                t1.Start();

                // Назначаем данные основной области на графике
                candleSeries = new Series("SeriesCandle")
                {
                    ChartType = SeriesChartType.Candlestick, // Тип - японские свечи
                    YAxisType = AxisType.Secondary,
                    ChartArea = "ChartAreaCandle",
                    ShadowOffset = 2,
                    YValuesPerPoint = 4
                };

                _chartForCandle.Series.Add(candleSeries);

                int counter = 0;
                foreach (Candle c in quotes)
                {
                    counter++;
                    // Добавление свечи
                    candleSeries.Points.AddXY(counter, c.Low, c.High, c.Open, c.Close);
                    // Добавление подписи-времени
                    candleSeries.Points[candleSeries.Points.Count - 1].AxisLabel = c.Date.ToString(CultureInfo.InvariantCulture);
                    // Назначение цветов свечей
                    if (c.IsPositive) candleSeries.Points[candleSeries.Points.Count - 1].Color = System.Drawing.Color.FromName(Program_Settings.PositiveCandleColor);
                    else candleSeries.Points[candleSeries.Points.Count - 1].Color = System.Drawing.Color.FromName(Program_Settings.NegativeCandleColor);
                }

                // Делаем курсор по Y красным и толстым
                candleArea.CursorX.LineColor = System.Drawing.Color.Red;
                candleArea.CursorX.LineWidth = 2;

                candleArea.AxisX.ScaleView.Position = 0;
                candleArea.AxisX.ScaleView.Size = 50;

                _chartForCandle.ChartAreas[0].AxisX.LabelStyle.Angle = -90; // Вертикальное расположение подписей дат
                _chartForCandle.ChartAreas[0].AxisX.IsLabelAutoFit = false;
                _chartForCandle.ChartAreas[0].AxisX.Interval = 5; // Интервал (кол-во свечей) между подписями дат
                candleArea.AxisY2.LabelStyle.Format = "#.###"; // Формат цены свечи
                candleArea.AxisY2.IntervalOffset = 1; // Что-бы было фиксированное кол-во надписей-цен свечей

                int startPozition = 0; // Первая отображаемая свеча
                int endPozition = candleSeries.Points.Count; // Последняя отображаемая свеча

                GetMinMaxValuesOnChart(startPozition, endPozition, out double min, out double max);
                candleArea.AxisY2.Maximum = max;
                candleArea.AxisY2.Minimum = min;

                ChartResize();
        }


public ChartGrid()
        {
            InitializeComponent();


            _chartForCandle = wfh.Child as Chart; // Получаем график из нашего контрола

            // Добавление обработчиков событий
            _chartForCandle.AxisScrollBarClicked += chartForCandle_AxisScrollBarClicked; // Щелчок по полосе прокрутки
            _chartForCandle.AxisViewChanged += chartForCandle_AxisViewChanged; // Изменение масштаба
            _chartForCandle.CursorPositionChanged += chartForCandle_CursorPositionChanged; // Изменение позиции курсора

            // Инициализируем основную область на графике
            candleArea = new ChartArea("ChartAreaCandle")
            {
                CursorX = { IsUserSelectionEnabled = true, IsUserEnabled = true },
                CursorY = { AxisType = AxisType.Secondary },
                Position = { Height = 70, X = 0, Width = 100, Y = 0 }, //чертa
            };

            _chartForCandle.ChartAreas.Add(candleArea); // Добавление основной области на график

        }
...
Рейтинг: 0 / 0
Асинхронная загрузка данных в Chart
    #39640946
Фотография Shocker.Pro
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
mraklbrwИ всё-таки, пробую сделать асинхронным подготовку контрола.Блин, учите матчасть.
Что толку от Invoke, если тупящий код выполняется в UI-потоке? UI при этом всё равно остановится. Вам говорят как надо, вы упорно пытаетесь съесть кактус
...
Рейтинг: 0 / 0
Асинхронная загрузка данных в Chart
    #39640948
Фотография Shocker.Pro
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
говнокод на маршеmraklbrw
Код: c#
1.
System.Drawing.Color.FromName()

зачем эту операцию выполнять 6000 раз?


mraklbrw
Код: c#
1.
c.Date.ToString(CultureInfo.InvariantCulture);

а это что, нельзя было заранее подготовить в виде строки, а не вычислять в UI-потоке?
...
Рейтинг: 0 / 0
Асинхронная загрузка данных в Chart
    #39640949
Фотография Shocker.Pro
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
mraklbrw
Код: c#
1.
GetMinMaxValuesOnChart

тут-то не смогли тормозов добавить, надеюсь?
...
Рейтинг: 0 / 0
Асинхронная загрузка данных в Chart
    #39640954
Фотография Petro123
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
mraklbrwИ всё-таки, пробую сделать асинхронным подготовку контрола.
)) упрямый.
Втыкает асинхронность и потоки там где они не нужны.
...
Рейтинг: 0 / 0
Асинхронная загрузка данных в Chart
    #39640956
Фотография mraklbrw
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Код: c#
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
66.
67.
68.
69.
70.
71.
72.
73.
74.
75.
76.
77.
78.
79.
80.
81.
82.
83.
private void ChartResize()
        {
            try
            {
                if (candleArea == null || candleSeries == null) return;

                int startPozition = 0; // Первая отображаемая свеча
                int endPozition = candleSeries.Points.Count; // Последняя отображаемая свеча

                if (_chartForCandle.ChartAreas.FindByName("ChartAreaCandle").AxisX.ScrollBar.IsVisible)
                {
                    // Если уже выбран какой-то диапазон, назначаем первую и последнюю исходя из этого диапазона
                    startPozition = Convert.ToInt32(candleArea.AxisX.ScaleView.Position);
                    endPozition = Convert.ToInt32(candleArea.AxisX.ScaleView.Position) + Convert.ToInt32(candleArea.AxisX.ScaleView.Size);
                }

                GetMinMaxValuesOnChart(startPozition, endPozition, out double min, out double max);
                candleArea.AxisY2.Maximum = max;
                candleArea.AxisY2.Minimum = min;

                candleArea.AxisX.ScaleView.Position = startPozition;
                candleArea.AxisX.ScaleView.Size = 50;

                // Запрос обновления индикторов
                if (_chartForCandle.ChartAreas.FindByName("ChartAreaVolume") != null) ResizeVolumeIndicator();

               _chartForCandle.Refresh();
               
            }
            catch (Exception ex) { }
        }

        /// <summary>
        /// Вычисление максимального и минимального значений на графике
        /// </summary>
        /// <param name="start">Начальнач свеча</param>
        /// <param name="end">Конечная свеча</param>
        /// <param name="min">Выходной параметр - минимальное значение</param>
        /// <param name="max">Выходной параметр - максимальное значение</param>
        private void GetMinMaxValuesOnChart(int start, int end, out double min, out double max)
        {
            min = double.MaxValue;
            max = double.MinValue;

            HashSet<Candle> quotes2 = new HashSet<Candle>(quotes.Skip(start).Take(end - start));

            foreach(Candle c in quotes2)
            {
                if (c.High > max) max = c.High;
                if (c.Low < min) min = c.Low;
            }
        }


/// <summary>
        /// Считывание котировок по заданному инструменту из файла
        /// </summary>
        /// <param name="quoteCode">Код инструмента</param>
        /// <returns></returns>
        public static HashSet<Candle> ReadQuotes(string quoteCode)
        {
            try
            {
                if (!File.Exists("Quotes/" + quoteCode + ".txt") || new FileInfo("Quotes/" + quoteCode + ".txt").Length < 10)
                    throw new Exception("Ошибка: для заданного инструмента сохранённых котировок нет.");
                HashSet<Candle> quotes = new HashSet<Candle>();
                using (StreamReader sr1 = new StreamReader("Quotes/" + quoteCode + ".txt"))
                {
                    while (!sr1.EndOfStream)
                    {
                        string tmp = sr1.ReadLine();
                        string[] quoteSemblance = tmp.Split(',');
                        quotes.Add(new Candle(quoteSemblance[0], quoteSemblance[1], quoteSemblance[2], quoteSemblance[3], quoteSemblance[4], quoteSemblance[5], quoteSemblance[6]));
                    }
                }
                return quotes;
            }
            catch (Exception ex)
            {
                MessageBox.Show("Проблема при считывании котировок " + quoteCode + " :" + ex.Message);
                return new HashSet<Candle>();
            }
        }



С вычислением цветов исправил, спасибо.
В данный момент:
сделал кнопку - при нажатии - вызов AddChart() ~ 2 секунды, из них ~ 300-350ms - загрузка котировок из файла.

Проверьте, пожалуйста, код в ReadQuotes().
...
Рейтинг: 0 / 0
Асинхронная загрузка данных в Chart
    #39640963
Фотография Shocker.Pro
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
mraklbrw
Код: c#
1.
new HashSet<Candle>(quotes.Skip(start).Take(end - start));

Это что за бред?
...
Рейтинг: 0 / 0
Асинхронная загрузка данных в Chart
    #39640965
Фотография mraklbrw
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Код: c#
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
/// <summary>
        /// Получение минимального значения на основной области графика
        /// </summary>
        private double GetMinValueOnChart(int start, int end)
        {
            double result = double.MaxValue;
            for (int i = start; i < end && i < quotes.Count; i++)
                if (quotes.ElementAt(i).Low < result) result = quotes.ElementAt(i).Low;
            return result;
        }

        /// <summary>
        /// Получение максимального значения на основной области графика
        /// </summary>
        private double GetMaxValueOnChart(int start, int end)
        {
            double result = 0;
            for (int i = start; i < end && i < quotes.Count; i++)
                if (quotes.ElementAt(i).High > result) result = quotes.ElementAt(i).High;
            return result;
        }



Было раньше так.
...
Рейтинг: 0 / 0
Асинхронная загрузка данных в Chart
    #39640967
Фотография Shocker.Pro
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Во-первых, в Linq есть агрегатные функции, зачем их имитировать? Впрочем тут может и есть смысл, чтобы сделать один проход вместо двух.

Во-вторых, HashSet не является коллекцией с детерминированной последовательностью элементов (сами же писали, что обращение по индексу к ней невозможно), следовательно позиционные операции с ним логического смысла не имеют
...
Рейтинг: 0 / 0
Асинхронная загрузка данных в Chart
    #39640968
Фотография Shocker.Pro
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Определения класса Candle вы не дали, поэтому смысл применения хэшсета вообще не очевиден. Объясните словами, зачем он применён.
...
Рейтинг: 0 / 0
Асинхронная загрузка данных в Chart
    #39640995
Фотография mraklbrw
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Candle - тут пока всё плохо с кодом
Код: c#
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
66.
67.
68.
69.
70.
71.
72.
73.
74.
75.
76.
77.
78.
79.
80.
81.
82.
83.
84.
85.
86.
87.
88.
89.
90.
91.
92.
93.
94.
95.
96.
97.
98.
99.
100.
101.
102.
103.
104.
105.
106.
107.
108.
109.
110.
111.
112.
113.
114.
115.
116.
117.
118.
119.
120.
121.
122.
123.
124.
125.
126.
127.
128.
129.
130.
131.
132.
133.
134.
135.
136.
137.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Trade
{
    public class Candle
    {
        public DateTime Date { get;}
        public float Open { get; }
        public float High { get; }
        public float Low { get; }
        public float Close { get; }
        public int Volume { get; }
        public bool IsPositive { get; } // Направление свечи - положительная или отрицательная


        /// <summary>
        /// Конструктор по умолчанию
        /// </summary>
        public Candle()
        {

        }

        /// <summary>
        /// Конструктор
        /// </summary>
        /// <param name="quoteString">Строка с данными-котировкой</param>
        public Candle(string quoteString)
        {
            string[] quoteSemblance = quoteString.Split(',');
            Date = new DateTime(Convert.ToInt32(quoteSemblance[0].Substring(0, 4)), Convert.ToInt32(quoteSemblance[0].Substring(4, 2)), Convert.ToInt32(quoteSemblance[0].Substring(6, 2)), Convert.ToInt32(quoteSemblance[1].Substring(0, 2)), Convert.ToInt32(quoteSemblance[1].Substring(2, 2)), Convert.ToInt32(quoteSemblance[1].Substring(4, 2)));
            Open = Convert.ToSingle(quoteSemblance[2].Replace('.', ','));
            High = Convert.ToSingle(quoteSemblance[3].Replace('.', ','));
            Low = Convert.ToSingle(quoteSemblance[4].Replace('.', ','));
            Close = Convert.ToSingle(quoteSemblance[5].Replace('.', ','));
            Volume = Convert.ToInt32(quoteSemblance[6]);
            IsPositive = Close > Open;
        }

        /// <summary>
        /// Конструктор
        /// </summary>
        /// <param name="date">Дата</param>
        /// <param name="open">Уровень открытия</param>
        /// <param name="high">Уровень-максимум</param>
        /// <param name="low">Уровень-минимум</param>
        /// <param name="close">Уровень закрытия</param>
        /// <param name="volume">Объём</param>
        public Candle(DateTime date, float open, float high, float low, float close, int volume)
        {
            Date = date;
            Open = open;
            High = high;
            Low = low;
            Close = close;
            Volume = volume;
            IsPositive = Close > Open;
        }

        /// <summary>
        /// Конструктор
        /// </summary>
        /// <param name="date">Дата</param>
        /// <param name="time">Время</param>
        /// <param name="open">Уровень открытия</param>
        /// <param name="high">Уровень-максимум</param>
        /// <param name="low">Уровень-минимум</param>
        /// <param name="close">Уровень закрытия</param>
        /// <param name="volume">Объём</param>
        public Candle(string date, string time, string open, string high, string low, string close, string volume)
        {
            Date = new DateTime(Convert.ToInt32(date.Substring(0, 4)), Convert.ToInt32(date.Substring(4, 2)), Convert.ToInt32(date.Substring(6, 2)), Convert.ToInt32(time.Substring(0, 2)), Convert.ToInt32(time.Substring(2, 2)), Convert.ToInt32(time.Substring(4, 2)));
            Open = Convert.ToSingle(open.Replace('.', ','));
            High = Convert.ToSingle(high.Replace('.', ','));
            Low = Convert.ToSingle(low.Replace('.', ','));
            Close = Convert.ToSingle(close.Replace('.', ','));
            Volume = Convert.ToInt32(volume);
            IsPositive = Close > Open;
        }

        public override bool Equals(object obj)
        {
            if (!(obj is Candle)) throw new Exception("Ошибка: попытка сравнения свечи с объектом другого типа");
            Candle c = obj as Candle;
            if (this == null || obj == null) return false;
            return (this.Date == c.Date && this.Open == c.Open && this.High == c.High && this.Low == c.Low && this.Close == c.Close && this.Volume == c.Volume);
        }

        public override string ToString()
        {
            return GetDate() + "," + GetTime() + "," + this.Open.ToString().Replace(',', '.') + "," + this.High.ToString().Replace(',', '.') + "," + this.Low.ToString().Replace(',', '.') + "," + this.Close.ToString().Replace(',', '.') + "," + this.Volume;
        }

        public override int GetHashCode()
        {
            //return (this.ToString().GetHashCode());
            return (Date.GetHashCode()); // Проверить - будет ли HashSet содержать только уникальные значения
        }

        /// <summary>
        /// Получение строкового предстваления даты свечи
        /// </summary>
        /// <returns></returns>
        public string GetDate()
        {
            string year = Date.Year.ToString();
            string month = Date.Month.ToString();
            if (month.Length == 1) month = "0" + month;
            string day = Date.Day.ToString();
            if (day.Length == 1) day = "0" + day;
            return year + month + day;
        }

        /// <summary>
        /// Получение строкового предстваления времени свечи
        /// </summary>
        /// <returns></returns>
        public string GetTime()
        {
            string hour = Date.Hour.ToString();
            if (hour.Length == 1) hour = "0" + hour;
            string minute = Date.Minute.ToString();
            if (minute.Length == 1) minute = "0" + minute;
            string second = Date.Second.ToString();
            if (second.Length == 1) second = "0" + second;
            return hour + minute + second;
        }

        
    }


}




HashSet - возможны ситуации, когда какая-то часть от загружаемых данных (допустим, процентов 5-7-10) иногда может повторяться, поэтому для того, чтобы не было повторяющихся данных.

Иначе каждый раз проверять данные считываемые.
...
Рейтинг: 0 / 0
Асинхронная загрузка данных в Chart
    #39641003
Фотография Shocker.Pro
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
mraklbrwможет повторяться, поэтому для того, чтобы не было повторяющихся данных.ну ок, но из-за этого вы теряете порядок следования элементов
...
Рейтинг: 0 / 0
Асинхронная загрузка данных в Chart
    #39641005
Фотография mraklbrw
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Да вроде на графике всё нормально выводится.
...
Рейтинг: 0 / 0
Асинхронная загрузка данных в Chart
    #39641009
Фотография Shocker.Pro
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Ну значит либо график сортирует сам,
либо из-за того, что
Код: c#
1.
2.
3.
4.
 public override int GetHashCode()
        {
            return (Date.GetHashCode()); 
        }

значения, отсортированные по хэшу, оказываются в нужной последовательности. Но так делать нельзя.
...
Рейтинг: 0 / 0
42 сообщений из 42, показаны все 2 страниц
Форумы / WPF, Silverlight [игнор отключен] [закрыт для гостей] / Асинхронная загрузка данных в Chart
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]