Measurement Studio for .NET Languages

cancel
Showing results for 
Search instead for 
Did you mean: 

WPF Graph - exception in NationalInstruments.Common.dll

Solved!
Go to solution

Hello.

I am using NI Graphs in my WPF application. The graphs are binded to ChartCollection<DateTime, double>. The application is appending every 1s the new point to the chart collection. The graphs are automatically refreshing and showing curves, but after some period (seems it is random period) the application sometimes stop with following exception:

 

A first chance exception of type 'System.ObjectDisposedException' occurred in NationalInstruments.Common.dll
An unhandled exception of type 'System.ObjectDisposedException' occurred in NationalInstruments.Common.dll
Additional information: The data store was modified.

 

2017-08-14_09h40_58.png

 2017-08-14_10h46_59.png

 

Here is graph XAML code:

 <Grid Grid.Column="2" Grid.Row="0" Grid.RowSpan="{Binding Path=testVoltageDropMeasurement, UpdateSourceTrigger=PropertyChanged, Mode=OneWay, Converter={StaticResource b2num2}}">
                                <ni:Graph x:Name="graph_temperatures" PreferIndexData="False" RenderMode="Raster">
                                    <ni:Graph.Axes>
                                        <ni:AxisDateTime Orientation="Horizontal"/>
                                        <ni:AxisDouble Label="Temperature [°C]" Orientation="Vertical" Range="0, 100, System.Double"/>
                                    </ni:Graph.Axes>
                                </ni:Graph>
                            </Grid>

 

Binding to ChartColletion is done programmatically only ones in the software:

// update graph data sources according to assigned channels
            graph_temperatures.Data.Clear(); // clear all data
            graph_temperatures.Plots.Clear(); // clear all plots
            if ((this.Test.temperatures != null) && (this.Test.temperatures.Count > 0))
            {
                for (int i = 0; i < this.Test.temperatures.Count; i++) // add plots for assigned channels
                {
                    graph_temperatures.Data[i] = this.Test.temperatures[i].values;
                    Plot p = new Plot();
                    LinePlotRenderer lpr = new LinePlotRenderer();
                    lpr.Stroke = (Brush)(new BrushConverter()).ConvertFromString(this.Test.temperatures[i].channelColor);
                    p.Renderer = lpr;
                    p.DataContext = this.Test.temperatures[i];
                    Binding b = new Binding()
                    {
                        Path = new PropertyPath("showed"),
                        Source = this.Test.temperatures[i],
                        Converter = new BooleanToVisibilityConverter()
                    };
                    p.SetBinding(Plot.VisibilityProperty, b);
                    graph_temperatures.Plots.Add(p);
                }
            }

 

See graphs in application:

2017-08-14_11h11_50.png

When I disable drawing of all channels (all show checkboxes are unchecked) the application is running well without any exception. I think the problem have to be in graphs controls.

Could you help me please to solve it?

 

Thank you for support.

0 Kudos
Message 1 of 10
(5,424 Views)

Based on the description and that it is a first-chance exception, I expect this is an issue with the chart being modified while the graph is processing a previous append in the background. We would need to see the full call stack to confirm but, assuming this is the case, the graph should handle this exception (and, if it occurs repeatedly, should automatically switch away from background data processing).

 

For chart data, it does make sense to configure the graph to use immediate data processing in the first place. To do this, set the "immediate updates" attached property.

 

In XAML:

xmlns:ni="http://schemas.ni.com/controls/2009/xaml/presentation"
xmlns:niPrimitives="http://schemas.ni.com/controls/2009/xaml/presentation/primitives"
...
<ni:Graph x:Name="graph_temperatures" niPrimitives:GraphConfiguration.ImmediateUpdates="True" ...

 

Or in code:

GraphConfiguration.SetImmediateUpdates( graph_temperatures, true );
~ Paul H
0 Kudos
Message 2 of 10
(5,394 Views)

Hello Paul. Thank you for answer. Unfortunately I couldn't find this function, see following print-screens:

 

2017-08-15_08h03_00.png

 

2017-08-15_08h02_17.png

 

There is usable only function for set draw visual cache size.

Jakub T.

0 Kudos
Message 3 of 10
(5,380 Views)

Sorry, my mistake: that functionality is not yet available in the current version of Measurement Studio.

 

Seeing the call stack from the exception would still be helpful in diagnosing the issue. Are you trying to modify the chart collection outside of the UI thread, like this question: Can't get Graph.DataSource to work in WPF i (threading issue?) ?

~ Paul H
0 Kudos
Message 4 of 10
(5,371 Views)

Yes, the chart collection is updated every 1s from another measuring thread. I supposed that the advantage of WPF controls is to be bound to datasource which can be updated independently. How the NI graph knows that the data was changed? Becasue I have chart collection defined as a following property which calls this property change event when changed, see:

 

private ChartCollection<DateTime, double> _values = new ChartCollection<DateTime, double>();
public ChartCollection<DateTime, double> values
{
     get { return _values; }
     set
     {
          if (_values != value)
          {
               _values = value;
               OnPropertyChanged("values");
            }
       }
}

 

public class ViewModelBase : INotifyPropertyChanged
    {
        public event PropertyChangedEventHandler PropertyChanged;
        protected void OnPropertyChanged(string propertyName)
        {
            if (this.PropertyChanged != null)
            {
                PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
            }
        }
    }

 

So you suggest me to update data in UI thread or call update from the delegate?

Thank you for support.

Jakub

0 Kudos
Message 5 of 10
(5,360 Views)


So you suggest me to update data in UI thread or call update from the delegate?

Yes, the chart collection types are not thread-safe, so they must be updated from the UI thread to guarantee correctness. Any of the approaches from the other question would work.

 


How the NI graph knows that the data was changed?

 Ultimately, the graph ends up listening to the DataChanged event, which lets it know and update automatically when values inside of the collection have changed.

~ Paul H
0 Kudos
Message 6 of 10
(5,353 Views)

Hello Paul.

Solved according your suggestions.

Thank you.

 

BTW, when do you plan to release the WPF graph controls with the new feature (immediate updates)? Does it solve this issue?

 

Jakub T.

0 Kudos
Message 7 of 10
(5,324 Views)
Solution
Accepted by topic author Zelva

First, I am afraid I do not know any details about the timing of the next Measurement Studio release.

 

The "immediate updates" setting is actually an option to return the graph to the UI-thread processing model that exists right now. (The new feature is for background-thread data processing, which can improve UI performance, but can also introduce more opportunities for cross-thread data invalidation.)

 


To give a little more background on the underlying issue, the disposed exception occurs because of an optimization made by the chart collection: when the graph requests access to the chart data, the chart returns a reference to the live data in the collection. This avoids a memory copy, but means that any change to the chart can invalidate the data held by the graph.

 

We have considered adding "thread-safe Append" methods to chart collections, but this would only end up doing the "dispatch to the UI thread" logic behind the scenes. In other words, to get this added convenience would mean a more complicated API (with limited opportunities for optimization), and it would end up hiding the inherent race conditions involved (ordering updates from multiple threads). Since the application is already performing multi-threaded operations, our conclusion so far has been that performing thread-safe chart updates is best left to that application.

~ Paul H
0 Kudos
Message 8 of 10
(5,312 Views)

OK, I understand. Thank you very much for the explanation and for the support.

Jakub

0 Kudos
Message 9 of 10
(5,309 Views)

Happy to help!

~ Paul H
0 Kudos
Message 10 of 10
(5,307 Views)