Measurement Studio for .NET Languages

cancel
Showing results for 
Search instead for 
Did you mean: 

graph freez ui and shows wrong values

Hello,

first at all im using Meassurement Studio 2013.

i have a lot of Timers in my Application. The Timers refresh some Values in my UI.

That works all like a Charme.My BIG Problem is now the GRaph from MEassurement Studio.

 

With following Code i load the aktual Values and refresh the Graph. If i do this with the Dispatchertimer oder with a normal Threading.Timer the Ui freezes and the Graph too. That caused that the Plots are wrong.

For example a GRaph Screenshot with two Plots. That are calculated Sinus-Curves. But they didn't look like.

GraphSinus.png

 

So, thats awfull 🙂

 

Here is my Code

   private System.Windows.Threading.DispatcherTimer _timer = new System.Windows.Threading.DispatcherTimer(System.Windows.Threading.DispatcherPriority.Render) { Interval = TimeSpan.FromMilliseconds(100) };

private void _timer_Tick(object sender, EventArgs e)
        {
            int j = 0;
            foreach (var item in this.ConfigurationViewModel.PlotConfigurations)
            {
                
                int numberOfPoints = 1;
                double[] data = new double[numberOfPoints];

                for (int i = 0; i < numberOfPoints; i++)
                {
                    try
                    {
                        var val = this.realTimeSystem.GetSingleValue(item.SelectedVariable.Identifier);
                        if (val == null)
                            break;
                        double valD = double.Parse(val.ToString());
                        data[i] = valD;
                    }
                    catch
                    {
                        this.logger.Log("Plot Exception for {0}", item.SelectedVariable);
                    }
                }
                if (data.Count() > 0)
                {
                    chartCollection[j].Append(data);
                }

                j++;
            }
        }

this is my chartcollection

 private CustomChartCollection[] _chartCollection;
        public CustomChartCollection[] chartCollection
        {
            get { return _chartCollection; }
            set { _chartCollection = value; RaisePropertyChanged("chartCollection"); }
        }



 chartCollection = new[] {
                                 new CustomChartCollection(),
                                 new CustomChartCollection(),
                                 new CustomChartCollection(),
                                 new CustomChartCollection(),
                                 new CustomChartCollection(),
                                 new CustomChartCollection(),
                                 new CustomChartCollection(),
                                 new CustomChartCollection(),
                };

 and here the class of the customchartcollection

#region CustomChartCollection-Class
    [DataTypeDescriptor(typeof(GraphDataCollectionDescriptor<>))]
    public class CustomChartCollection : ChartCollection<double>
    {
        public CustomChartCollection() : base(100000) { }

        protected override void OnDataChanged(GraphCollectionChangedEventArgs e)
        {
            base.OnDataChanged(new GraphCollectionChangedEventArgs(0));
        }
    }

    #endregion

 

 

and here is the XAML of my Graph

 

  <ni:Graph 
                    x:Name="graph"
                    DataSource="{Binding chartCollection}" 
                    RenderMode="Raster" 
                    PreferIndexData="True"
                    SuppressScaleLayout="True"
                    PlotAreaBackground="{Binding GraphBackgroundBrush}"
                          
                   nix:GraphExtensions.PlotsSource="{Binding Plots2}"
                   nix:GraphExtensions.AxesSource="{Binding GraphAxes}">

                        </ni:Graph>

 

 

So what i'm doing wrong ? Is the Dispatchertimer with 100 ms to slow ?

Or is it better to work with to Timers and make it with addRange ?

 

Thanks in advance

 

Nice Wishes

0 Kudos
Message 1 of 9
(6,371 Views)

I am trying to reproduce your issue locally: how are your axes configured (range, adjuster, etc)? It would be very helpful if you could attach a stand-alone project that reproduces the problem using simulated data.

~ Paul H
0 Kudos
Message 2 of 9
(6,364 Views)

Hi Paul,

i tried to generate a Application that is like my real Application.

In my real Application i have an own Thread that fills some Variables with the current Values. In my Graph-thread i pick the Currentvalues everey 100 ms (i think this is to slow).

 

I dont know how to make the Graph smoother to scroll. In our Winforms Application we have a buffer and we write every 100ms abou 500 Values into the Graph. I don't know how to do this with WPF.

Hope you can help me.

Manuel

0 Kudos
Message 3 of 9
(6,353 Views)

So your concern is with updating a WPF graph with one sample every 100 ms, as opposed to updating a Windows Forms graph with 500 samples every 100 ms? From your earlier code, in the _timer_Tick handler you set numberOfPoints = 1, retrieve the one value with realTimeSystem.GetSingleValue, and then append the data array containing that one value to the corresponding chart collection. If you increase the size of the data array, you can append multiple points at once to the chart collection.


If that is not your issue, please let me know what I should be looking for in the test application you provided. The only "pause" I saw was when the data went past the default size of the window. Otherwise, with the whole graph in view, it appeared to update continuously as values were appended.

~ Paul H
0 Kudos
Message 4 of 9
(6,339 Views)

Hi Paul,

sure you can help me. I agree with you that 100 ms one Point is not the same as 500 Points.

 

I need a possibility to load more Values in a List with Datetime and the Value. i hahve two x-Axis in my Graph. One for example has the Range 0 - 60 ( this means 0seconds to 60 seconds). This Axis is visible. And i have one invisible Axis that is coninious.

 

Actually i append every 100 ms a Point. So the Graph set the x-Axis automaticly.

I need now a possibility so set more Points to the Graph with an x,y Point. So the Graph didn't set the X-Axis automaticly.

In Winforms it was very easy. I need to port this to WPF.

 

Can you build me an Example wich has two threads. One thread fills an Array with Points (x,y) and the Other thread Appends the Array to the GRaph. The Graph shoul have a fixed x-Axis with 0-60 (this where my seconds) and also should be continous chart.

 

Do you know what i mean. Its very tricky i think

 

Thanks

Manuel

0 Kudos
Message 5 of 9
(6,335 Views)

Without knowing the Windows Forms API you used, it is difficult to recommend a WPF equivalent.


That said, here is a simple producer/consumer example in WPF, based on your requirements for x,y time/sample values, two threads, limiting UI updates to 100 ms, and a fixed horizontal reference axis:


    XAML:
    <ni:Graph x:Name="graph" RenderMode="Raster">
        <ni:Graph.Axes>
            <ni:AxisDouble Orientation="Horizontal" Range="0,60" Adjuster="ContinuousChart" Visibility="Collapsed" />
            <ni:AxisDouble Orientation="Horizontal" Range="0,60" Adjuster="None" InteractionMode="None" />
        </ni:Graph.Axes>
    </ni:Graph>

    Code:
    public partial class MainWindow : Window {
        private readonly BlockingCollection<Point> _simulatedData;
        private readonly ChartCollection<double, double> _graphData;
        private readonly DispatcherTimer _consumerTimer;

        public MainWindow( ) {
            InitializeComponent( );

            // Start producer.
            _simulatedData = new BlockingCollection<Point>( );
            Task.Factory.StartNew( this.SimulateData );

            // Start consumer.
            _graphData = new ChartCollection<double, double>( 100000 );
            graph.DataSource = _graphData;
            _consumerTimer = new DispatcherTimer(
                TimeSpan.FromMilliseconds( 100 ),
                DispatcherPriority.Normal,
                this.ConsumeData,
                this.Dispatcher );
        }

        private void SimulateData( ) {
            Random random = new Random( );
            DateTime start = DateTime.UtcNow;
            while( true ) {
                TimeSpan time = DateTime.UtcNow - start;
                double value = random.NextDouble( );
                _simulatedData.Add( new Point( time.TotalSeconds, value ) );
                Thread.Sleep( 25 );
            }
        }

        private void ConsumeData( object sender, EventArgs e ) {
            // Pull all the currently available data from the simulated data source.
            int count = _simulatedData.Count;
            double[] times = new double[count];
            double[] values = new double[count];
            for( int i = 0; i < count; ++i ) {
                Point sample = _simulatedData.Take( );
                times[i] = sample.X;
                values[i] = sample.Y;
            }

            // Append all the accumulated values to the graph's data collection at once.
            _graphData.Append( times, values );
        }
    }

~ Paul H
0 Kudos
Message 6 of 9
(6,317 Views)

Hi Paul,

thanks for you help, but this doesnt work in my Application 😞

Please see the Atachment.

 

0 Kudos
Message 7 of 9
(6,298 Views)

hi Paul,

i got it working now. My Demo-Application works very well. But when i tried it in my real-Application i got an Exception

"Index values must be strictly increasing.
Parametername: index"

 

and this where my index-Values

{ChartCollection<Double,Double>: Capacity=10000, Count=69}
    [0]: {Sample<Double,Double>: Index=0,4605921, Value=0,108677158764633}
    [1]: {Sample<Double,Double>: Index=0,6341268, Value=0,108677158764633}
    [2]: {Sample<Double,Double>: Index=0,7841568, Value=0,108677158764633}
    [3]: {Sample<Double,Double>: Index=0,9341868, Value=0,108677158764633}
    [4]: {Sample<Double,Double>: Index=1,0842168, Value=0,108677158764633}
    [5]: {Sample<Double,Double>: Index=1,2912582, Value=0,108677158764633}
    [6]: {Sample<Double,Double>: Index=1,4487897, Value=0,108677158764633}
    [7]: {Sample<Double,Double>: Index=1,6493298, Value=0,108677158764633}
    [8]: {Sample<Double,Double>: Index=1,7998599, Value=0,108677158764633}
    [9]: {Sample<Double,Double>: Index=1,9498899, Value=0,108677158764633}
    [10]: {Sample<Double,Double>: Index=2,0999199, Value=0,108677158764633}
    [11]: {Sample<Double,Double>: Index=2,2499499, Value=0,108677158764633}
    [12]: {Sample<Double,Double>: Index=2,3999799, Value=0,108677158764633}
    [13]: {Sample<Double,Double>: Index=2,5500099, Value=0,108677158764633}
    [14]: {Sample<Double,Double>: Index=2,7000399, Value=0,108677158764633}
    [15]: {Sample<Double,Double>: Index=2,8500699, Value=0,108677158764633}
    [16]: {Sample<Double,Double>: Index=3,0000999, Value=0,108677158764633}
    [17]: {Sample<Double,Double>: Index=3,1501299, Value=0,108677158764633}
    [18]: {Sample<Double,Double>: Index=3,3566712, Value=0,108677158764633}
    [19]: {Sample<Double,Double>: Index=3,5587116, Value=0,108677158764633}
    [20]: {Sample<Double,Double>: Index=3,770754, Value=0,108677158764633}
    [21]: {Sample<Double,Double>: Index=3,9402879, Value=0,108677158764633}
    [22]: {Sample<Double,Double>: Index=4,1153229, Value=0,108677158764633}
    [23]: {Sample<Double,Double>: Index=4,2823563, Value=0,108677158764633}
    [24]: {Sample<Double,Double>: Index=4,4598918, Value=0,108677158764633}
    [25]: {Sample<Double,Double>: Index=4,6184235, Value=0,108677158764633}
    [26]: {Sample<Double,Double>: Index=4,7949588, Value=0,108677158764633}
    [27]: {Sample<Double,Double>: Index=4,9724943, Value=0,108677158764633}
    [28]: {Sample<Double,Double>: Index=5,1535305, Value=0,108677158764633}
    [29]: {Sample<Double,Double>: Index=5,3095617, Value=0,108677158764633}
    [30]: {Sample<Double,Double>: Index=5,4665931, Value=0,108677158764633}
    [31]: {Sample<Double,Double>: Index=5,6196237, Value=0,108677158764633}
    [32]: {Sample<Double,Double>: Index=5,8636725, Value=0,108677158764633}
    [33]: {Sample<Double,Double>: Index=6,0202038, Value=0,108677158764633}
    [34]: {Sample<Double,Double>: Index=6,1992396, Value=0,108677158764633}
    [35]: {Sample<Double,Double>: Index=6,3497697, Value=0,108677158764633}
    [36]: {Sample<Double,Double>: Index=6,4997997, Value=0,108677158764633}
    [37]: {Sample<Double,Double>: Index=6,6498297, Value=0,108677158764633}
    [38]: {Sample<Double,Double>: Index=6,7998597, Value=0,108677158764633}
    [39]: {Sample<Double,Double>: Index=6,9498897, Value=0,108677158764633}
    [40]: {Sample<Double,Double>: Index=7,1044206, Value=0,108677158764633}
    [41]: {Sample<Double,Double>: Index=7,2589515, Value=0,108677158764633}
    [42]: {Sample<Double,Double>: Index=7,4089815, Value=0,108677158764633}
    [43]: {Sample<Double,Double>: Index=7,5590115, Value=0,108677158764633}
    [44]: {Sample<Double,Double>: Index=7,7235444, Value=0,108677158764633}
    [45]: {Sample<Double,Double>: Index=7,8735744, Value=0,108677158764633}
    [46]: {Sample<Double,Double>: Index=8,0236044, Value=0,108677158764633}
    [47]: {Sample<Double,Double>: Index=8,2221441, Value=0,108677158764633}
    [48]: {Sample<Double,Double>: Index=8,3721741, Value=0,108677158764633}
    [49]: {Sample<Double,Double>: Index=8,5222041, Value=0,108677158764633}
    [50]: {Sample<Double,Double>: Index=8,6722341, Value=0,108677158764633}
    [51]: {Sample<Double,Double>: Index=8,8222641, Value=0,108677158764633}
    [52]: {Sample<Double,Double>: Index=8,9722941, Value=0,108677158764633}
    [53]: {Sample<Double,Double>: Index=9,1228242, Value=0,108677158764633}
    [54]: {Sample<Double,Double>: Index=9,2728542, Value=0,108677158764633}
    [55]: {Sample<Double,Double>: Index=9,4228842, Value=0,108677158764633}
    [56]: {Sample<Double,Double>: Index=9,5729142, Value=0,108677158764633}
    [57]: {Sample<Double,Double>: Index=9,7324461, Value=0,108677158764633}
    [58]: {Sample<Double,Double>: Index=9,8824761, Value=0,108677158764633}
    [59]: {Sample<Double,Double>: Index=10,0325061, Value=0,108677158764633}
    [60]: {Sample<Double,Double>: Index=10,1825361, Value=0,108677158764633}
    [61]: {Sample<Double,Double>: Index=10,3330662, Value=0,108677158764633}
    [62]: {Sample<Double,Double>: Index=10,4830962, Value=0,108677158764633}
    [63]: {Sample<Double,Double>: Index=10,6331262, Value=0,108677158764633}
    [64]: {Sample<Double,Double>: Index=10,7941584, Value=0,108677158764633}
    [65]: {Sample<Double,Double>: Index=10,9446885, Value=0,108677158764633}
    [66]: {Sample<Double,Double>: Index=11,0947185, Value=0,108677158764633}
    [67]: {Sample<Double,Double>: Index=11,2447485, Value=0,108677158764633}
    [68]: {Sample<Double,Double>: Index=11,3947785, Value=0,108677158764633}

 

So the index is increasing. Don't know what this error means 😕

0 Kudos
Message 8 of 9
(6,293 Views)

Sorry, it was my mistake.

Now it works.

I will make some tests ang give you feedback as soon as possible.

Manuel

0 Kudos
Message 9 of 9
(6,291 Views)