1

I'm currently using a similar structure to the 50 EEG example. Part of my design is to add and delete 10-50 function plots on the fly, so it is important that I managed my memory effectively. When I run the memory profiler in VS2015, I find that everytime I try to a function plot from the collection, SciChart.Charting.Visuals.Axes.LabelProviders.NumericTickLabel still lingers in memory. What would be the proper way to dispose NumericTickLabel or remove a scichartsurface?

XAML.CS

    <ResourceDictionary>
       <DataTemplate x:Key="FunctionItemTemplate">
       <Grid>
           <s:SciChartSurface Name=FunctionSurface
                              RenderableSeries="{Binding RenderableSeriesCollections}"/>

       </Grid>
    </ResourceDictionary>

    <ListView Name="FunctionPlots
          ItemTemplate="{StaticResource FunctionItemTemplate}"
          ItemsSource="{Binding FunctionsCollection}" />

MainWindowViewModel.cs

public class MainWindowViewModel : INotifyProperty
{
       private ObservableCollection<FunctionPlotViewModel> _functionsCollection;

       public MainWindowViewModel()
       {
           FunctionsCollection = new ObservableCollection<FunctionPlotViewModel>();
       }

       public ObservableCollection<FunctionPlotViewModel> FunctionsCollection
       {
             get { return _functionsCollection;}
             set 
             {
                   _functionsCollection = value;
                   OnPropertyChanged("FunctionsCollection");     
             }  
       }

       public void RemoveLastFunctionPlot()
       {
              int lastIndex = FunctionCollections.Count - 1;
              FunctionCollections.Remove(lastIndex);
              //Doesn't Collect
              GC.Collect();
              GC.WaitForPendingFinalizer();
              GC.Collect();
       }

       public event PropertyChangedEventHanlder PropertyChanged;
       protected void OnPropertyChanged(string name)
       {
                PropertyChangedEventHanlder handler = PropertyChanged;

                if (handler != null)
                {
                    handler(this, new PropertyChangedEventArgs(name));

                }
        }

}

FunctionPlotViewModel.cs

 public class FunctionPlotViewModel: INotifyProperty
    {
       private ObservableCollection<IRenderableSeries> _renderableSeriesCollections;

       public FunctionPlotViewModel()
       {
           RenderableSeriesCollection = new ObservableCollection<IRenderableSeries>();
       }

       public ObservableCollection<IRenderableSeries> RenderableSeriesCollections
       {
             get { return _renderableSeriesCollections;}
             set 
             {
                   _renderableSeriesCollections= value;
                   OnPropertyChanged("RenderableSeriesCollections");     
             }  
       }

       public  void SetUpCustomAxis(double TimeOfDayInitial, IAxis AxisToBindTo)
       {
             var defaultSurface = RenderableSeriesCollections.FirstOrDefault().DataSeries.ParentSurface();
              if(defaultSurface == null)
              {
                  return;
              }
              var newAxis = new NumericAxis();
              var customNumericLabel = new CustomNumericLabelProvider();
              defaultSurface.XAxis = newAxis;
              Binding visibleRangeBinding = new Binding("VisibleRange");
              visibleRangeBinding.Source = AxisToBindTo;
              visibleRangeBinding.Mode = BindingMode.TwoWay;
              ((NumericAxis)defaultSurface.XAxis).SetBinding(NumericAxis.VisibleRangeProperty, visibleRangeBinding);

       }

       public void CleanUp()
       {
           var defaultSurface = RenderableSeriesCollections.FirstOrDefault().DataSeries.ParentSurface();
              if(defaultSurface == null)
              {
                  return;
              }
           foreach(var renderSeries in RenderableSeriesCollections)
           {
                renderSeries.DataSeries.Clear();
           }
           RenderableSeriesCollections.Clear();
           var token  = defaultSurface.SuspendUpdates();
           token.Dispose();

           //More things to do??
       }

       public event PropertyChangedEventHanlder PropertyChanged;
       protected void OnPropertyChanged(string name)
       {
                PropertyChangedEventHanlder handler = PropertyChanged;

                if (handler != null)
                {
                    handler(this, new PropertyChangedEventArgs(name));

                }
        }

}

CustomNumericLabelProvider.cs

     public class CustomNumericLabelProvider : NumericProvider
     {
       public override void OnBeginAxisDraw()
       {
       }

       public override string FormatLabel(IComparable dataValue)
       {
            if (dataValue == null)
                return String.Emtpy;
            return ConvertToTimeOfDay(dataValue);

       }

       public string ConvertToTimeOfDay(IComparable value)
       {
             //commented out for brevity
             return value;
       }

       public override string FormatCursorLabel(IComparable dataValue)
       {
            //commented out for brevity
            return dataValue;
       }

    }
ntmt
  • 163
  • 1
  • 1
  • 11

1 Answers1

0

According to the SciChart documentation, SciChartSurface implements the Finalizer and Dispose patterns, which calls dispose on child elements when a chart is unloaded from memory.

The documentation also shows the RenderSurface implements Finalize so resources should be automatically cleaned up when a chart is no longer held by any objects.

If you experience anything different, it is probably a bug.

The best thing to do is to check if you are using the latest version of SciChart from their NuGet feed, and after that, if the issue still occurs, to submit a bug report with code to reproduce the bug to tech support.

Dr. Andrew Burnett-Thompson
  • 20,980
  • 8
  • 88
  • 178