使用WPF和Oxyplot缓慢更新UI

时间:2014-08-19 00:15:01

标签: c# wpf csv oxyplot

我想在这里完成的是我想从CSV文件中获取一些数据,我从一个文件夹中复制并放入一个临时文件夹(所以我不会篡改原文)。

然后我想读取CSV文件中的所有数据,并使用Oxyplot中的Scatter Series绘制图表上的最后2000个数据点(我希望每隔200 ms检查一次新数据,因此我使用了Dispatcher Timer )。我遇到的问题是,对情节的前几次更新看起来很棒并且它确切地描绘了我想要它...但是,在可能12次更新之后图形不会更新,或者更新非常缓慢导致UI变为不响应。

以下是该部分项目的代码......

    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
        }
    }

这是MainWindowModel中的LoadData方法......

    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分并将它们添加到图表中。

也许我需要考虑一个后台工作者?

我可能会想到这一切都错了,如果我是,我很想知道我应该去哪个方向!我很擅长编写这么大的项目和必须实时运行的项目。请放轻松我:)并提前感谢。

1 个答案:

答案 0 :(得分:1)

一些建议:

在LoadData()方法中使用秒表来查看它需要多长时间。你没有说这些文件中有多少数据,但Linq的一些东西看起来可能会受益于一些优化 - 在同一组数据上有很多ToLists()和重复Selects 。像这样:

var sw = new Stopwatch();
sw.Start();

... do your stuff

Debug.WriteLine(sw.ElapsedMilliseconds);

您还可以在计时器代表中尝试秒表,以查看整个“周期”需要多长时间,以防万一需要超过200毫秒。我不知道DispatcherTimer是否会遭受重新入侵,定时器会在之前的“tick”完成之前再次触发,这会降低性能。

问题可能在于您的图表组件。在使用大型WPF DataGrids时,我遇到了类似的问题 - 创建数据并不是特别重要 - 它是需要花费时间的渲染。在LoadData()结束时,我看到你清理图表系列然后重新填充它。我发现使用大型DataGrid的数据源执行此操作会创建“双重打击”,因为它在Clear()之后呈现,然后在重新填充数据后再次呈现。我不熟悉OxyPlot,但看看你是否可以找到一种替代方法,如果可行,例如重新使用该系列,而不是清理并再次添加。

如果性能不佳确实是OxyPlot,那么购买不同的图表组件是一种选择吗?我可以完全推荐SciChart,我们一直在使用SciChart用于各种高性能/大批量科学图表应用程序(我没有附属于他们!)。