简体   繁体   English

实时图表性能问题 c# winform

[英]Real Time chart performance issue c# winform

I am currently using liveChart to plot a real time graph of 3 values: a position, a load and a deformation.我目前正在使用 liveChart 绘制 3 个值的实时图:位置、载荷和变形。 The program is based on the Doli.DoPE library (a proprietary dll)该程序基于 Doli.DoPE 库(一个专有的 dll)

In MainForm.cs , there is an event that is triggered everytime the sensor records a new value (every millisecond or so).MainForm.cs ,每次传感器记录一个新值(每毫秒左右)时都会触发一个事件。

public void Initialisation()
{
   //...    
   MyEdc.Eh.OnDataHdlr += new DoPE.OnDataHdlr(OnData)
   //...
}

with

private int OnData(ref DoPE.OnData Data, object Parameter)
{
    DoPE.Data Sample = Data.Data;
    if (Data.DoPError == DoPE.ERR.NOERROR)
    {
        Int32 Time = Environment.TickCount;
        if ((Time - LastTime) >= 250 /*ms*/)
        {
            // Send the data from the ondata handler inside of a global list
            ListData.time.Add(Sample.Time);
            ListData.position.Add(Sample.Sensor[(int)DoPE.SENSOR.SENSOR_S]);
            ListData.load.Add(Sample.Sensor[(int)DoPE.SENSOR.SENSOR_F]);
            ListData.extend.Add(Sample.Sensor[(int)DoPE.SENSOR.SENSOR_E]);

            Thread ThForUpdateChart = new Thread(() =>
            {
                if (NewINstanceOfChart != null)
                { NewINstanceOfChart.UpdateValues(ListData.time.Last(), ListData.position.Last(),ListData.load.Last(), ListData.extend.Last()); }
            });
            ThForUpdateChart.Start();
            LastTime = Time;
        }
    }
    return 0;
}

The function UpdateValues is part of a second form RealTimeChart.cs called in the MainForm through a button click event:函数UpdateValues是通过按钮单击事件在 MainForm 中调用的第二个窗体RealTimeChart.cs一部分:

private void btnGraph_Click(object sender, EventArgs e)
{
    var thread = new Thread(() =>
    {
        NewINstanceOfChart = new RealTimeChart(ListData);
        NewINstanceOfChart.Show();
    });
    thread.Start();
}

the form RealTimeCharts.cs is initalised this way:表单RealTimeCharts.cs是这样初始化的:

public RealTimeChart(Globals ListData)
{
    InitializeComponent();

    //measures = ListData;

    ListPosition = new ChartValues<ObservablePoint>();
    for (int i = 0; i < measures.load.Count(); i++)
    {
        ListPosition.Add(new ObservablePoint
        {
            X = measures.time[i],
            Y = measures.position[i]
        });
    }
    ListLoad = new ChartValues<ObservablePoint>();
    for (int i = 0; i < measures.load.Count(); i++)
    {
        ListLoad.Add(new ObservablePoint
        {
            X = measures.time[i],
            Y = measures.load[i]
        });
    }

    ListExtend = new ChartValues<ObservablePoint>();
    for (int i = 0; i < measures.load.Count(); i++)
    {
        ListExtend.Add(new ObservablePoint
        {
            X = measures.time[i],
            Y = measures.extend[i]
        });
    }

    resultChart.Series.Add(new LineSeries
    {
        LineSmoothness = 0,
        Values = ListPosition,
        PointGeometrySize = 2,
        StrokeThickness = 4
    });


    SetXAxisLimits();

}

And the UpdateValues function is defined as followed: UpdateValues函数定义如下:

        public void UpdateValues(double time, double position, double load, double extend)
        {
            measures.time.Add(time-measures.TareTime);
            measures.position.Add(position);
            measures.load.Add(load);
            measures.extend.Add(extend);

            UpdateEnabledSequencialPartToTrue();

        }



        public void UpdateEnabledSequencialPartToTrue()
        {
            if (this.InvokeRequired)
                BeginInvoke(new System.Action(() => this.InternalUpdateEnabledSequencialPartToTrue()));
            else
                InternalUpdateEnabledSequencialPartToTrue();
        }
        private void InternalUpdateEnabledSequencialPartToTrue()
        {
            try
            {
                ListPosition.Add(new ObservablePoint
                {
                    X = measures.time.Last(),
                    Y = measures.position.Last()
                });

                ListLoad.Add(new ObservablePoint
                {
                    X = measures.time.Last(),
                    Y = measures.load.Last()
                });

                ListExtend.Add(new ObservablePoint
                {
                    X = measures.time.Last(),
                    Y = measures.extend.Last()
                });

                //LineSeries plot = new LineSeries();
                SetXAxisLimits();

                // lets only use the last 14400 values (1h long recording, 14400 values at frequency of 1 record very 250ms, see OnData function MainForm
                if (measures.time.Count > 14400)
                {
                    ListPosition.RemoveAt(0);
                    ListLoad.RemoveAt(0);
                    ListExtend.RemoveAt(0);
                }
            }
            catch (NullReferenceException) { }
        }

After a minute, the programme starts to be really laggy.一分钟后,程序开始变得非常滞后。 I tried putting the second winform (RealTimeCharts) on another thread so the MainForm does not lag (it is piloting a machine, it has to be responsive), but no success.我尝试将第二个 winform (RealTimeCharts) 放在另一个线程上,以便 MainForm 不会滞后(它正在驾驶一台机器,它必须具有响应性),但没有成功。

I would like to know if the whole thing is laggy because the code is way too bad, or if it is liveChart that reached its (free) limits.我想知道整个事情是否因为代码太糟糕而滞后,或者是否是 liveChart 达到了(免费)限制。 Would you advice another way to plot real time data ?你会建议另一种绘制实时数据的方法吗?

In MainForm.cs, there is an event that is triggered everytime the sensor records a new value (every millisecond or so).在 MainForm.cs 中,每次传感器记录新值时(每毫秒左右)都会触发一个事件。

That is natturally way higher then what Winforms Drawing can take.这自然比 Winforms Drawing 可以接受的要高得多。 See, drawing a GUI is expensive.看,绘制 GUI 是昂贵的。 If you only do it once per user-triggered event, you will never notice that.如果您对每个用户触发的事件只执行一次,您将永远不会注意到这一点。 But do it from a loop - including sampling a sensor every MS - and you can quickly overlord the UI.但是从循环中进行 - 包括每个 MS 对传感器进行采样 - 并且您可以快速控制 UI。 My first Multithreading tests actually appeared to have failed on big numbers, becaus I ended up sending so many updates I plain overloaded the GUI thread.我的第一个多线程测试实际上似乎在大数字上失败了,因为我最终发送了如此多的更新,我显然使GUI 线程过载。 Since then I know not to go past progress bars.从那时起我就知道不要越过进度条。

You can add data to a background collection as quickly as you can sample them, but you can not draw that quickly.您可以尽可能快地将数据添加到背景集合中,但您无法快速绘制。 And honestly drawing more often then 30-60 times/second (every ~17 ms) is not really going to help anyone anyway.老实说,比 30-60 次/秒(每约 17 毫秒)更频繁地绘制无论如何都不会真正帮助任何人。 Usually you can not use a timer, as the Tick might happen more often then it can be processed - again, a GUI Thread with a overflowing Event Queue.通常你不能使用计时器,因为 Tick 可能会更频繁地发生,然后它可以被处理 - 同样,一个带有溢出事件队列的 GUI 线程。

I do not have any rate limiting code for WindowsForms.我没有 WindowsForms 的任何速率限制代码。 But I would guess an Event that re-queues itself at the end of the EventQueue after finishing the work would work.但我猜想在完成工作后在 EventQueue 末尾重新排队的事件会起作用。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM