Member 13980927 Ответов: 1

Память превышает, при использовании нескольких сроков (40 линий) графика в WPF. Во всяком случае, чтобы уменьшить его?


Я пытаюсь смоделировать многострочный график с помощью библиотеки chartingToolkit в Wpf. График/диаграмма должна работать по крайней мере в течение 8-10 часов. Существует проблема линейного увеличения памяти процесса (до 800 МБ и более). Мне нужно построить график данных в реальном времени с последовательного Com-порта (разные ведомые устройства). Я вызываю 2 процесса UpadateValue и UpdateChart из DispatcherTimer.


Во время работы этой программы память процесса линейно увеличивается со временем (более 900 МБ наблюдается из Диспетчера задач..!!).

Пожалуйста, предложите мне некоторые вещи, чтобы решить проблему с памятью.

Большое спасибо

Что я уже пробовал:

публичный частичный класс MainWindow : Window
{
Коллекция ObservableCollection&ЛТ;KeyValuePair&ЛТ;инт инт&ГТ;&ГТ; Collection0 = новая коллекция ObservableCollection&ЛТ;KeyValuePair&ЛТ;инт инт&ГТ;&ГТ;();
Коллекция ObservableCollection&ЛТ;KeyValuePair&ЛТ;инт инт&ГТ;&ГТ; коллекции collection1 = новая коллекция ObservableCollection&ЛТ;KeyValuePair&ЛТ;инт инт&ГТ;&ГТ;();
/*..........продолжить.............*/
Коллекция ObservableCollection&ЛТ;KeyValuePair&ЛТ;инт инт&ГТ;&ГТ; Collection39 = новая коллекция ObservableCollection&ЛТ;KeyValuePair&ЛТ;инт инт&ГТ;&ГТ;();

Random rnd = новый случайный();
public int i = 0;

публичное главное окно()
{
метод InitializeComponent();

Параллель.Invoke(() => { SetTimer1(); });
Параллель.Invoke(() => { SetTimer2(); });
}

частный недействительными SetTimer1()
{
DispatcherTimer dispatcherTimer = новый DispatcherTimer();
диспетчер таймер.Tick += new EventHandler(ValueUpdate);
диспетчер таймер.Интервал = новый временной интервал(0, 0, 0, 2, 0);
диспетчер таймер.Начать();
}

частный недействительными SetTimer2()
{
DispatcherTimer dispatcherTimer = новый DispatcherTimer();
диспетчер таймер.ТИК += новый EventHandler(ChartUpdate);
диспетчер таймер.Интервал = новый временной интервал(0, 0, 0, 2, 0);
диспетчер таймер.Начать();
}

частная ValueUpdate недействительным(объект отправителя, EventArgs в электронной)
{
инт м = -40;
СБОРЩИК МУСОРА.Собирать();
Collection0.Добавить(новый KeyValuePair&ЛТ;инт инт&ГТ;(я, рнд.Рядом(м++, м++)));
Коллекции collection1.Добавить(новый KeyValuePair&ЛТ;инт инт&ГТ;(я, рнд.Рядом(м++, м++)));
/*......продолжить......*/
Collection39.Добавить(новый KeyValuePair&ЛТ;инт инт&ГТ;(я, рнд.Рядом(м++, м++)));
i = i + 1;
СБОРЩИК МУСОРА.Собирать();

}

ChartUpdate недействительным(объект отправителя, EventArgs в электронной)
{
СБОРЩИК МУСОРА.Собирать();
LineChart0.DataContext = Collection0;
LineChart1.Класс DataContext = Коллекции Collection1;
/*.....продолжить.....*/
LineChart39.Класс DataContext = Collection39;
СБОРЩИК МУСОРА.Собирать();
}
}

1 Ответов

Рейтинг:
2

Dirk Bahle

Интересная задача - но решение ее довольно трудно достижимо:

1) Один из способов справиться с проблемой памяти-это пройти через ваши временные ряды через регулярные промежутки времени и через детали, скажем, вы смотрите на каждую точку в течение 5 секунд, и вы усредняете эти 5 точек и заменяете их средним значением, которое вы видели
- это приводит к меньшей детализации, но может быть нормально, если вам просто нужен общий тренд, и вы освободите память из 4 точек данных, используя только 1 точку данных в результате

2) Когда я думаю о вашей проблеме, это больше похоже на проблему данных, чем на проблему WPF. Итак, еще одно "очевидное" решение состоит в том, чтобы сбросить ваши точки данных в хранилище (SQLite SQL Server), которое является достаточно большим и быстрым, а затем иметь возможность управлять отображением только ограниченной/конечной части этого ряда данных. Таким образом, вы не теряете данных и всегда можете работать над различными способами отображения результатов - например, показывать усредненные данные, когда пользователь уменьшает масштаб, или показывать детали, когда вы увеличиваете масштаб.

Это много работы и не так просто реализовать, но довольно интересно - надеюсь, это поможет.


Member 13980927

Спасибо за быстрый ответ. Требование состоит в том, чтобы показать данные в течение 8 часов(от начальной точки). Ваш второй пункт кажется хорошим, могу ли я сбросить последовательные данные в базу данных и показывать все данные каждые 5 секунд на диаграмме?

Dirk Bahle

Да, именно это я и имел в виду, вы могли бы, в зависимости от количества ваших точек данных и количества точек, которые вам нужно показать, построить различные уровни агрегированных/усредненных представлений - скажем, у вас есть детализированная таблица с необработанными данными (уровень 0), а затем вы могли бы иметь таблицу данных уровня 1, где каждая точка данных уровня 1 представляет среднее значение последних 100 точек данных в таблице уровня 0.

В зависимости от ваших потребностей вы можете усреднить более 1000 вместо 100 баллов или использовать несколько уровней агрегированных таблиц уровня 0, уровня 1, уровня 3 ... если первая таблица содержит все необработанные данные, а каждая вторая таблица усредненные значения более 100 баллов на уровне 0, то 100 баллов усреднены на уровне 1 ...

"Очевидно", что ваши таблицы будут становиться меньше по мере того, как уровень 0,1,2 ... увеличивается, и вы также можете поддерживать различные представления деталей на вашем графике. Обновление должно быть очень сложным, так как вы будете вычислять средние значения только каждые 100 или около того записей...