Медленное обновление интерфейса с помощью WPF и Oxyplot

1

То, что я пытаюсь выполнить здесь, я хочу получить некоторые данные из 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 точек и добавить их в график.

Может быть, мне нужно рассмотреть фонового работника?

Я мог бы все это ошибаться, и если бы я был бы рад узнать, в каком направлении я должен идти! Я новичок в программировании таких больших проектов, которые должны работать в режиме реального времени. Пожалуйста, успокойтесь со мной :) и спасибо заранее.

Теги:
csv
wpf
oxyplot

1 ответ

1

Некоторые предложения:

Используйте секундомер в вашем методе 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!).

  • 0
    Спасибо за ответ! На самом деле я использовал секундомер, чтобы отслеживать, сколько времени занимает сбор данных, он постепенно увеличивается, потому что файл CSV постоянно записывается (самое длинное - почти 300 мс, я просто хочу, чтобы мое приложение проверяло новые данные каждые 200 мс) ). Я не уверен, что размер данных вызывает проблему, потому что я только беру последние 2000 точек и строю их. Я думаю, что вы правы в отношении узкого места, существующего в рендеринге, хотя я неопытен в C #, мне трудно понять, как добавить в серию. Кроме того, эти ToList () фанки ...
  • 0
    * трудно добавить в серию вместо того, чтобы уничтожить ее и полностью перестроить. Я хочу, чтобы график был рабочим стилем, означающим новейшие данные с правой стороны. Когда поступают новые данные, эти данные сдвигаются влево ... это единственный способ, которым я могу это сделать.
Показать ещё 3 комментария

Ещё вопросы

Сообщество Overcoder
Наверх
Меню