SciChart® the market leader in Fast WPF Charts, WPF 3D Charts, and iOS Chart & Android Chart Components

0
0

It seems like a memory leak of sciChartSurface. After call Dispose(), some sciChartSurfaces are also refrenced by MouseManager and can’t release.

I also use ants memory profiler, but this web page can’t upload images and attachments, it alerts Forbidden!

The leak instance reference chain is:
MouseManager.I -> Dictionary<string,IList<Mouse.IReceiveMouseEvents>> -> SciChart.Core.Utility.Mouse.IReceiveMouseEvents[] -> SciChart.Charting.ChartModifiers.ModifierGroup -> SciChart.Charting.Visuals.SciChartSurface .

Below is the key code:

>

    private SciChartSurface sciTickPriceChartSurface;
    private FastLineRenderableSeries lastPriceLineRenderableSeries;
    private SciChartSurface sciTickVolumeChartSurface;
    private FastLineRenderableSeries volumeLineRenderableSeries;

    private void LoadSciTickCharts()
    {
        // set sciTickPriceChartSurface xAxis
        var nowDateTime = DateTime.Now; 
        var todayDate = nowDateTime.Date;

        // set sciTickPriceChartSurface
        sciTickPriceChartSurface = new SciChartSurface();
        sciTickPriceChartSurface.ViewportManager = new TickChartViewportManager(todayDate);

        var priceChartXAxis = new DiscontinuousDateTimeAxis
        {
            DrawLabels = false,
            MajorDelta = new TimeSpan(1, 0, 0),
            MinorDelta = new TimeSpan(0,12,0),
            MinimalZoomConstrain = new TimeSpan(1,0,0),
            AutoTicks = false,
            DrawMajorGridLines = true,
            DrawMinorGridLines = false,
            AutoRange = AutoRange.Never,
            LabelProvider = new TickDateTimeAxisLabelProvider(),
            //Calendar = new LSECalendar(), 
            VisibleRange = new DateRange(nowDateTime - new TimeSpan(1,0,0), nowDateTime + new TimeSpan(3,0,0)),
        };

        sciTickPriceChartSurface.XAxes.Add(priceChartXAxis);

        // set sciTickPriceChartSurface yAxis
        var priceYAxis = new NumericAxis
        {
            DrawMajorGridLines = true,
            DrawMinorGridLines = false,
            AutoRange = AutoRange.Always,
            GrowBy = new DoubleRange(0.2, 0.2)
        };
        sciTickPriceChartSurface.YAxes.Add(priceYAxis);

        // lastPriceLineSeries
        lastPriceLineRenderableSeries = new FastLineRenderableSeries
        {
            Stroke = Color.FromArgb(0xFF, 0xFF, 0xFF, 0xFF),
            StrokeThickness = 1,
            DataSeries = new XyDataSeries<DateTime, double>(),
        };
        sciTickPriceChartSurface.RenderableSeries.Add(lastPriceLineRenderableSeries);
        CursorModifier.SetSnapToSeries(lastPriceLineRenderableSeries, true);

        // sciTickVolumeChartSurface
        sciTickVolumeChartSurface = new SciChartSurface();

        // set sciTickVolumeChartSurface yAxis
        var volumeYAxis = new NumericAxis
        {
            DrawMajorGridLines = true,
            DrawMinorGridLines = false,
            AutoRange = AutoRange.Always,
            GrowBy = new DoubleRange(0, 0)
        };
        sciTickVolumeChartSurface.YAxes.Add(volumeYAxis);

        var volumeChartXAxis = new DiscontinuousDateTimeAxis
        {
            DrawLabels = true,
            MajorDelta = new TimeSpan(1, 0, 0),
            MinorDelta = new TimeSpan(0, 12, 0),
            MinimalZoomConstrain = new TimeSpan(1, 0, 0),
            AutoTicks = false,
            DrawMajorGridLines = true,
            DrawMinorGridLines = false,
            AutoRange = AutoRange.Never,
            LabelProvider = new TickDateTimeAxisLabelProvider(),
            //Calendar = new LSECalendar()
        };
        sciTickVolumeChartSurface.XAxes.Add(volumeChartXAxis);

        // Bind the VisibleRange of chart2.XAxis.VisibleRange to chart1.XAxis.VisibleRange TwoWay
        var xAxisVisibleRangeBinding = new Binding("VisibleRange")
        {
            Source = priceChartXAxis,
            Mode = BindingMode.TwoWay,
        };
        BindingOperations.SetBinding(volumeChartXAxis, SciChart.Charting.Visuals.Axes.AxisBase.VisibleRangeProperty, xAxisVisibleRangeBinding);

        // volumeLineSeries
        volumeLineRenderableSeries = new FastLineRenderableSeries
        {
            Stroke = Color.FromArgb(0xFF, 0x0, 0xFF, 0xFF),
            StrokeThickness = 1,
            DataSeries = new XyDataSeries<DateTime, long>(),
        };
        sciTickVolumeChartSurface.RenderableSeries.Add(volumeLineRenderableSeries);
        CursorModifier.SetSnapToSeries(volumeLineRenderableSeries, true);

        var grid = new Grid();
        grid.RowDefinitions.Add(new RowDefinition { Height = new GridLength(2, GridUnitType.Star) });
        grid.RowDefinitions.Add(new RowDefinition { Height = new GridLength(1, GridUnitType.Auto) });
        grid.RowDefinitions.Add(new RowDefinition { Height = new GridLength(1, GridUnitType.Star) });

        var gridSplitter = new GridSplitter
        {
            MinHeight = 4,
            HorizontalAlignment = HorizontalAlignment.Stretch,
            Background = new SolidColorBrush(Color.FromRgb(0xFF, 0xFF, 0x0))
        };

        Grid.SetRow(sciTickPriceChartSurface, 0);
        Grid.SetRow(gridSplitter, 1);
        Grid.SetRow(sciTickVolumeChartSurface, 2);

        grid.Children.Add(sciTickPriceChartSurface);
        grid.Children.Add(gridSplitter);
        grid.Children.Add(sciTickVolumeChartSurface);

        var priceChartSurfaceModifier = new ModifierGroup(

            // Allow pan on Left mouse drag
            new ZoomPanModifier { ExecuteOn = ExecuteOn.MouseLeftButton, ClipModeX = SciChart.Charting.ClipMode.None },
            // <!-- Allow Mousewheel Zoom -->
            new MouseWheelZoomModifier(),
            // <!-- Allow Zoom to Extents on double click -->
            new TickChartZoomExtentsModifier { ExecuteOn = ExecuteOn.MouseDoubleClick },
            // Alow cursor modifier
            new CursorModifier
            {
                SourceMode = SourceMode.AllSeries,
                ShowTooltipOn = ShowTooltipOptions.Always,
                ShowAxisLabels = true,
                ReceiveHandledEvents = true,
                ShowTooltip = true,
                IsEnabled = true,
            }
        );
        sciTickPriceChartSurface.ChartModifier = priceChartSurfaceModifier;

        var volumeChartSurfaceModifier = new ModifierGroup(

            // Allow pan on Left mouse drag
            new ZoomPanModifier { ExecuteOn = ExecuteOn.MouseLeftButton, ClipModeX = SciChart.Charting.ClipMode.None },
            // <!-- Allow Mousewheel Zoom -->
            new MouseWheelZoomModifier(),
            // <!-- Allow Zoom to Extents on double click -->
            new TickChartZoomExtentsModifier { ExecuteOn = ExecuteOn.MouseDoubleClick },
            // Alow cursor modifier
            new CursorModifier
            {
                SourceMode = SourceMode.AllSeries,
                ShowTooltipOn = ShowTooltipOptions.Always,
                ShowAxisLabels = true,
                ReceiveHandledEvents = true,
                ShowTooltip = true,
                IsEnabled = true,
            }
        );
        sciTickVolumeChartSurface.ChartModifier = volumeChartSurfaceModifier;

        var tickChartsMouseEventSharedGroupName = UUIDHelper.CreateUUIDString(false).ToString();
        MouseManager.SetMouseEventGroup(priceChartSurfaceModifier, tickChartsMouseEventSharedGroupName);
        MouseManager.SetMouseEventGroup(volumeChartSurfaceModifier, tickChartsMouseEventSharedGroupName);

        var tickChartSharedGroupName = UUIDHelper.CreateUUIDString(false).ToString();
        SciChartGroup.SetVerticalChartGroup(sciTickPriceChartSurface, tickChartSharedGroupName);
        SciChartGroup.SetVerticalChartGroup(sciTickVolumeChartSurface, tickChartSharedGroupName);

        this.ChartGrid.Children.Clear();
        this.ChartGrid.Children.Add(grid);
    }

    public void Dispose()
    {
        if (isDisposed == true) return;
        isDisposed = true;

        // Don't forget to clear chart grid child list.
        ChartGrid.Children.Clear();

        if (sciTickPriceChartSurface != null)
        {
            // Chart's Dispose method needs to be called when chart is 
            // no longer needed so that all unmanaged resources 
            // (DirectX etc.) are released.
            sciTickPriceChartSurface.ChartModifier?.OnDetached();
            sciTickPriceChartSurface?.Dispose();
            sciTickPriceChartSurface = null;

        }
        if (sciTickVolumeChartSurface != null)
        {
            // Chart's Dispose method needs to be called when chart is 
            // no longer needed so that all unmanaged resources 
            // (DirectX etc.) are released.
            sciTickVolumeChartSurface?.ChartModifier?.OnDetached();
            sciTickVolumeChartSurface?.Dispose();
            sciTickVolumeChartSurface = null;
        }
        GC.SuppressFinalize(this);
    }
Version
5.1.1.11473
  • You must to post comments
0
0

Hi there,

Under normal operation, there is no need to call SciChartSurface.Dispose(), as SciChartSurface implements the Finalizer pattern and will automatically clear its resources when the chart is garbage collected.

However, you have set MouseManager.MouseEventGroup attached property, which causes two surfaces to be linked together (in static dictionary as you have discovered with ANTS). This may prevent garbage collection in the first place. You can try to unset this property (set to null) when the surface is no longer needed. Can you try that?

Finally – I am testing image attachments

Best regards,
Andrew

Images
  • You must to post comments
Showing 1 result
Your Answer

Please first to submit.