xtian79

Memory Leak creating symbology for Legend Control

Discussion created by xtian79 on Jun 24, 2014
Latest reply on Jun 25, 2014 by xtian79
DEAR PEOPLE FROM THE FUTURE: Here's what we've figured out so far???

I developed an application that creates a GraphicLayer and draw in it 827 graphics (polylines) using the ArcGIS runtime 10.2.2, each object has it own symbology defined using the following code to create the renderer:

private UniqueValueRenderer GetUniqueValueRenderer(GraphicsLayer layer, string attributeField)
        {
            var uniqueValueRenderer = new UniqueValueRenderer();
            var defaultSymbol = new ESRI.ArcGIS.Client.Symbols.SimpleLineSymbol { Width = 2.5 };
            uniqueValueRenderer.Field = attributeField;

            var colorRange = new ColorRange { From = this.GetRandomColor(), To = this.GetRandomColor() };

            var rampInterpolator = new RampInterpolator { ColorRange = colorRange };

            foreach (var graphic in layer.Graphics)
            {
                var valueInfo = new UniqueValueInfo
                            {
                                Label = graphic.Attributes[attributeField].ToString(),
                                Value = graphic.Attributes[attributeField].ToString(),
                                Symbol =
                                    rampInterpolator.GetInterpolatedSymbol(
                                            defaultSymbol, 
                                            graphic, 
                                            0, 
                                            layer.Graphics.Count, 
                                            layer.Graphics.IndexOf(graphic))
                            };
                uniqueValueRenderer.Infos.Add(valueInfo);
            }

            return uniqueValueRenderer;
        }


In a workflow, I added the layer, remove it from the list of layers and then added again. In the last step of this workflow, the application launch the following exception:

Exception from HRESULT: 0x88980003 in the PresentationCore.dll with the following callstack:

PresentationCore.dll!System.Windows.Media.Imaging.RenderTargetBitmap.FinalizeCreation() + 0xd8 bytes 
  PresentationCore.dll!System.Windows.Media.Imaging.RenderTargetBitmap.RenderTargetBitmap(int pixelWidth, int pixelHeight, double dpiX, double dpiY, System.Windows.Media.PixelFormat pixelFormat) + 0x169 bytes 
  ESRI.ArcGIS.Client.dll!ESRI.ArcGIS.Client.LegendSymbol.CreateImageSnapshot() + 0x2c8 bytes 
  ESRI.ArcGIS.Client.dll!ESRI.ArcGIS.Client.LegendSymbol.ToImageSource.AnonymousMethod__1() + 0x2b bytes 
  WindowsBase.dll!System.Windows.Threading.ExceptionWrapper.InternalRealCall(System.Delegate callback, object args, int numArgs) + 0x128 bytes 
  WindowsBase.dll!MS.Internal.Threading.ExceptionFilterHelper.TryCatchWhen(object source, System.Delegate method, object args, int numArgs, System.Delegate catchHandler) + 0x47 bytes 
  WindowsBase.dll!System.Windows.Threading.DispatcherOperation.InvokeImpl() + 0x281 bytes 
  mscorlib.dll!System.Threading.ExecutionContext.RunInternal(System.Threading.ExecutionContext executionContext, System.Threading.ContextCallback callback, object state, bool preserveSyncCtx) + 0x285 bytes 
  mscorlib.dll!System.Threading.ExecutionContext.Run(System.Threading.ExecutionContext executionContext, System.Threading.ContextCallback callback, object state, bool preserveSyncCtx) + 0x9 bytes 
  mscorlib.dll!System.Threading.ExecutionContext.Run(System.Threading.ExecutionContext executionContext, System.Threading.ContextCallback callback, object state) + 0x57 bytes 
  WindowsBase.dll!System.Windows.Threading.DispatcherOperation.Invoke() + 0x71 bytes 
  WindowsBase.dll!System.Windows.Threading.Dispatcher.ProcessQueue() + 0x2a1 bytes 
  WindowsBase.dll!System.Windows.Threading.Dispatcher.WndProcHook(System.IntPtr hwnd, int msg, System.IntPtr wParam, System.IntPtr lParam, ref bool handled) + 0xb3 bytes 
  WindowsBase.dll!MS.Win32.HwndWrapper.WndProc(System.IntPtr hwnd, int msg, System.IntPtr wParam, System.IntPtr lParam, ref bool handled) + 0x14a bytes 
  WindowsBase.dll!MS.Win32.HwndSubclass.DispatcherCallbackOperation(object o) + 0x80 bytes 
  WindowsBase.dll!System.Windows.Threading.ExceptionWrapper.InternalRealCall(System.Delegate callback, object args, int numArgs) + 0x5a bytes 
  WindowsBase.dll!MS.Internal.Threading.ExceptionFilterHelper.TryCatchWhen(object source, System.Delegate method, object args, int numArgs, System.Delegate catchHandler) + 0x47 bytes 
  WindowsBase.dll!System.Windows.Threading.Dispatcher.LegacyInvokeImpl(System.Windows.Threading.DispatcherPriority priority, System.TimeSpan timeout, System.Delegate method, object args, int numArgs) + 0x2bc bytes 
  WindowsBase.dll!MS.Win32.HwndSubclass.SubclassWndProc(System.IntPtr hwnd, int msg, System.IntPtr wParam, System.IntPtr lParam) + 0x140 bytes 
  [Native to Managed Transition] 
  [Managed to Native Transition] 
  WindowsBase.dll!System.Windows.Threading.Dispatcher.PushFrameImpl(System.Windows.Threading.DispatcherFrame frame) + 0x112 bytes 
  PresentationFramework.dll!System.Windows.Application.RunInternal(System.Windows.Window window) + 0x17a bytes 
  PresentationFramework.dll!System.Windows.Application.Run() + 0x67 bytes 
  Rosen.Clients.Infrastructure.IntegrityManagement.exe!Rosen.Clients.Infrastructure.IntegrityManagement.App.Main() + 0x77 bytes C#


If i set a SimpleRenderer for the layer, it does not show any issue.
Reading the call stack and watching the behavior of the application, the symbols on the map are drawn but the application crash whe it tries to create the symbology for the legend control.

so far i have been trying to release memory when the layer is removed:


public void RemoveLayer()
        {
            var layerItemViewModels = this.SelectedLayers;
            if (layerItemViewModels != null)
            {
                var layerItemViewModel = layerItemViewModels.FirstOrDefault();
                if (layerItemViewModel != null)
                {
                    var selectedLayer = layerItemViewModel.Layer.DisplayName;
                    var layerToRemove = layerItemViewModel.Layer;
                    if (this.VisibleLayers.Contains(layerToRemove) && !(layerToRemove is ArcGISLocalTiledLayer || layerToRemove is ArcGISTiledMapServiceLayer))
                    {
                        var group = layerToRemove as GroupLayer;
                        if (group != null)
                        {
                            var layerIdList = group.GetLayerIdListFromGroup();
                            foreach (var layerId in layerIdList)
                            {
                                this.VisibleLayers.RemoveLayer(layerId);
                            }
                        }
                        else
                        {
                            this.VisibleLayers.RemoveLayer(layerToRemove.ID);
                        }

                        this.VisibleLayers.Remove(layerToRemove); // aqui se remueve el layer
                        if (layerToRemove is GraphicsLayer)
                        {
                            this.CleanLayerInstances(layerToRemove as GraphicsLayer);
                            this.CleanLayerItemViewModel(layerItemViewModel);
                        }
                        GC.Collect();
                        GC.WaitForPendingFinalizers();
                        GC.Collect();

                    }
                    else
                    {
                        foreach (var layer in this.VisibleLayers)
                        {
                            if (layer is GroupLayer)
                            {
                                this.RemoveLayerFromGroupLayer(layer as GroupLayer, selectedLayer);
                            }
                        }
                    }
                }
            }
        }

        private void CleanLayerItemViewModel(LayerItemViewModel layerItemViewModel)
        {
            foreach (var legendItem in layerItemViewModel.LegendItems.ToArray())
            {
                layerItemViewModel.LegendItems.Remove(legendItem);
            }
        }

        private void CleanLayerInstances(GraphicsLayer layer)
        {
            foreach (var graphic in layer.Graphics.ToList())
            {
                    if (graphic.Geometry is Polyline)
                    {
                        var line = graphic.Geometry as Polyline;
                        foreach (var path in line.Paths.ToList())
                        {
                            line.Paths.Remove(path);
                            path.Clear();
                        }
                        
                        line.Paths = null;
                    }

                graphic.MapTip = null;
                graphic.Geometry = null;
                layer.Graphics.Remove(graphic);
            }
            
            layer.Graphics = null;
        }


So far I still get the same exception

Outcomes