То, что я пытаюсь выполнить здесь, я хочу получить некоторые данные из CSV файла, который я копирую из одной папки и помещаю в временную папку (поэтому я не вмешиваюсь в оригинал).
Затем я хочу прочитать все данные из файла CSV и построить последние 2000 точек данных на графике с использованием серии Scatter в Oxyplot (я хочу, чтобы это проверяло новые данные каждые 200 мс, поэтому я использовал диспетчерский таймер). Проблема, с которой я сталкиваюсь, заключается в том, что первые несколько обновлений сюжета выглядят великолепно, и он показывает, как именно я хочу... однако, возможно, после 12 обновлений график не обновляется или обновляется очень медленно, заставляя пользовательский интерфейс отвечать на запросы.
Ниже мой код для этой части проекта...
public MainWindow()
{
viewModel = new View_Model.MainWindowModel();
DataContext = viewModel;
CompositionTarget.Rendering += CompositionTargetRendering;
InitializeComponent();
}
private void AutoUpdateGraph() //begins when a check box IsChecked = true
{
sw.Start();
System.Windows.Threading.DispatcherTimer dispatcherTimer = new System.Windows.Threading.DispatcherTimer();
dispatcherTimer.Tick += new EventHandler(dispatcherTimer_Tick);
dispatcherTimer.Interval = new TimeSpan(0, 0, 0, 0, 200);
dispatcherTimer.Start();
}
private void dispatcherTimer_Tick(object sender, EventArgs e)
{
SleeveData sd = new SleeveData(); //class to deal with the data
FileManagement fm = new FileManagement(); //class to manage the files
string date = fm.GetDate(); //get the current date to use in finding the
//most recent CSV file
_newPath = fm.InitialFileSetup(date); //create a new path for the temp file
fm.RewriteFile(_newPath); //write the temp file to the temp path
if (fm.IsFileLocked(_newPath) == false) //checking if the file is being written to
{
IEnumerable<SleeveData> newSD = sd.GetMostRecentCSVData(_newPath); //getting the latest data from the temp file
viewModel.LoadData(newSD); //updating the data on the graph
}
}
И вот метод LoadData в MainWindowModel...
public void LoadData(IEnumerable<SleeveData> newData)
{
var scatterSeries1 = new OxyPlot.Series.ScatterSeries
{
MarkerSize = 3,
Title = string.Format("Sleeve Data"),
};
int j = 0;
var zeroBuffer = new List<float>(new float[2000]);
var fDiaDataBuffer = zeroBuffer.Concat((newData.Select(x => x.fDiameter).ToList())).ToList();
var iDiaDataBuffer = zeroBuffer.Concat((newData.Select(x => x.IDiaMax).ToList())).ToList();
for (int i = fDiaDataBuffer.Count - 2000; i <= fDiaDataBuffer.Count - 1; i++)
{
scatterSeries1.Points.Add(new ScatterPoint(j, fDiaDataBuffer[i]));
j++;
}
PlotModel.Series.Clear();
PlotModel.Series.Add(scatterSeries1);
}
Я делаю некоторые напуганные вещи, чтобы получить последние 2000 точек и добавить их в график.
Может быть, мне нужно рассмотреть фонового работника?
Я мог бы все это ошибаться, и если бы я был бы рад узнать, в каком направлении я должен идти! Я новичок в программировании таких больших проектов, которые должны работать в режиме реального времени. Пожалуйста, успокойтесь со мной :) и спасибо заранее.
Некоторые предложения:
Используйте секундомер в вашем методе LoadData(), чтобы узнать, сколько времени он занимает. Вы не может сказать, сколько данных в этих файлах, но некоторые вещи Linq, похоже, может извлечь выгоду из некоторой оптимизации - есть много ToLists()
и повторяются Selects
на тот же набор данных. Что-то вроде этого:
var sw = new Stopwatch();
sw.Start();
... do your stuff
Debug.WriteLine(sw.ElapsedMilliseconds);
Вы также можете попробовать секундомер в делегате таймера, чтобы посмотреть, как долго длится весь "цикл", на всякий случай, если он занимает больше 200 мс. Я не знаю, может ли DispatcherTimer пострадать от повторного входа, когда таймер срабатывает снова до завершения предыдущего "галочки", что ухудшит производительность.
Проблема может заключаться в компоненте составления диаграмм. У меня были аналогичные проблемы при работе с большими WPF DataGrids. Создание данных не особенно облагается налогом - это рендеринг, который занимает время. В конце LoadData() я вижу, что вы очищаете серию диаграмм, а затем повторно заселяете ее. Я обнаружил, что выполнение этого с источником данных для большого DataGrid создает "double-whammy", как оно появляется после Clear(), а затем снова отображает после повторной обработки данных. Я не знаком с OxyPlot, но вижу, можно ли найти альтернативный подход, если это возможно, например, повторное использование серии, а не очистка и добавление снова.
Если плохая производительность оказывается OxyPlot, вы покупаете другой компонент диаграммы? Я могу полностью рекомендовать SciChart, который мы использовали для различных приложений с высокой производительностью/высоким объемом научных диаграмм (я не связан с ними btw!).