Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/wpf/13.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 使用WPF和Oxyplot缓慢更新UI_C#_Wpf_Csv_Oxyplot - Fatal编程技术网

C# 使用WPF和Oxyplot缓慢更新UI

C# 使用WPF和Oxyplot缓慢更新UI,c#,wpf,csv,oxyplot,C#,Wpf,Csv,Oxyplot,我想在这里完成的是,我想从一个CSV文件中获取一些数据,然后从一个文件夹复制到一个临时文件夹中(这样我就不会篡改原始文件) 然后,我想读取CSV文件中的所有数据,并使用Oxyplot中的散点序列在图形上绘制最后2000个数据点(我想每200ms检查一次新数据,所以我使用了调度程序计时器)。我遇到的问题是,最初几次更新的情节看起来很棒,它的情节正是我想要的。。。但是,在12次更新之后,图形不会更新,或者更新速度非常慢,导致UI变得无响应 下面是我的代码为这一部分的项目 public Mai

我想在这里完成的是,我想从一个CSV文件中获取一些数据,然后从一个文件夹复制到一个临时文件夹中(这样我就不会篡改原始文件)

然后,我想读取CSV文件中的所有数据,并使用Oxyplot中的散点序列在图形上绘制最后2000个数据点(我想每200ms检查一次新数据,所以我使用了调度程序计时器)。我遇到的问题是,最初几次更新的情节看起来很棒,它的情节正是我想要的。。。但是,在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
        }
    }
public主窗口()
{
viewModel=新视图_Model.MainWindowModel();
DataContext=viewModel;
CompositionTarget.Rendering+=CompositionTargetRendering;
初始化组件();
}
private void AutoUpdateGraph()//在选中复选框时开始=true
{
sw.Start();
System.Windows.Threading.dispatchermer dispatchermer=新的System.Windows.Threading.dispatchermer();
dispatchermer.Tick+=新事件处理程序(dispatchermer\u Tick);
Dispatchermer.Interval=新的时间跨度(0,0,0,0,200);
dispatchermer.Start();
}
私有void Dispatcher_Tick(对象发送方,事件参数e)
{
SleeveData sd=new SleeveData();//处理数据的类
FileManagement fm=new FileManagement();//类来管理文件
string date=fm.GetDate();//获取用于查找
//最新的CSV文件
_newPath=fm.InitialFileSetup(date);//为临时文件创建一个新路径
RewriteFile(_newPath);//将临时文件写入临时路径
if(fm.IsFileLocked(_newPath)==false)//检查文件是否正在写入
{
IEnumerable newSD=sd.GetMostRecentCSVData(_newPath);//从临时文件获取最新数据
viewModel.LoadData(newSD);//更新图形上的数据
}
}
这是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);
    }
public void LoadData(IEnumerable newData)
{
var scatterSeries1=新OxyPlot.Series.ScatterSeries
{
MarkerSize=3,
Title=string.Format(“套管数据”),
};
int j=0;
var zeroBuffer=新列表(新浮点[2000]);
var fDiaDataBuffer=zeroBuffer.Concat((newData.Select(x=>x.fDiameter.ToList()).ToList();
var iDiaDataBuffer=zeroBuffer.Concat((newData.Select(x=>x.IDiaMax.ToList()).ToList();
对于(inti=fDiaDataBuffer.Count-2000;i一些建议:

在LoadData()方法中使用秒表来查看它需要多长时间。您不会说这些文件中有多少数据,但Linq的一些东西似乎可以从一些优化中受益-在同一组数据上有许多
ToLists()
和重复的
选择
。类似如下:

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

... do your stuff

Debug.WriteLine(sw.ElapsedMilliseconds);
您也可以尝试在计时器委托中使用秒表,以查看整个“周期”需要多长时间,以防它需要超过200毫秒。我不知道调度程序是否会出现重入,即在前一个“滴答”完成之前计时器再次启动,这会降低性能

问题可能出在您的图表组件上。我在使用大型WPF数据网格时遇到过类似的问题-创建数据并不特别费力-需要花费时间的是渲染。在LoadData()的末尾我看到您清除了图表系列,然后重新填充它。我发现对大型DataGrid的数据源执行此操作会产生“双重打击”,因为它会在清除()之后呈现,然后在重新填充数据后再次渲染。我不熟悉OxyPlot,但如果可行,请查看是否可以找到替代方法,例如重新使用序列,而不是清除并再次添加


如果OxyPlot的性能确实很差,那么购买不同的图表组件是一种选择吗?我可以完全推荐SciChart,我们已经将其用于各种高性能/高容量的科学图表应用程序(顺便说一句,我与他们没有关系!).

谢谢你的回复!我确实用秒表来监控抓取数据所花的时间,它会越来越大,因为CSV文件一直在被写入(最长的时间几乎是300毫秒,我只希望我的应用程序每隔200毫秒检查一次新数据)。我不确定数据的大小是否导致了问题,因为我只获取了最后2000个点并绘制它们。我认为您对渲染中存在的瓶颈是正确的,尽管我对C#缺乏经验,但我发现很难找出如何添加到序列中。还有,那些ToList()s是时髦的…*发现很难添加到序列中,而不是将其删除并完全重建。我希望图形是一种运行样式,表示右侧的最新数据。当收到新数据时,数据会被推到左侧…这是我可以完成此任务的唯一方法。@JoshRyan假设不断添加行对于从未删除的文件,如何跟踪您绘制的最后一个行号。在下一个计时器勾选时,读取文件并跳过此行号,然后遍历所有剩余的行,创建散点并将其添加到现有系列(类似于
PlotModel.series[0].Points.add(…)'))。如果系列中的点数为2001,则
PlotModel.series.RemoveAt(0)`,这将为您提供“运行”的打印样式。无需在每个刻度上清除并重新创建整个系列!@JoshRyan我认为对于文件大小不断增长的问题,您无能为力。您已经