jjoalland13

Memory Leak with Graphic Tracker

Discussion created by jjoalland13 on Nov 29, 2012
Latest reply on Sep 19, 2013 by jjoalland13
I'm working on application which will never shutdown... the main interface is containing a MapControl control, in order for the application to dynamicaly display on the map data received from other applications.
We are developing with ArcGIS Engine 10.0 SP4, C#.net and Visual Studio 2010.
We use GraphicTracker (4 to manage display order) to draw geometries (points and curve polylines).

We currently face a Memory Leak for this application when doing stress tests : we send data to the application every second or 2 seconds, each time the application must clean the Graphic Tracker, release all COM Objects and draw again new data on the Graphic Tracker. after 2 or 3 hours, we reach an OutOfMemory Exception or -2147467259 runtime error... But our application is a 24/24 hours system and should never stop, neither restart !

I guess, my release objects methods are wrong, but can't find a solution...

So could somebody look to my code for any solutions or ideas ?

Form1 = simple Form with MapControl + 2 buttons to start/stop a 1 second Timer which send clean/drawing order for 10000
public partial class Form1 : Form
    {
        ...

        private void Form1_Load(object sender, EventArgs e)
        {
            // Load on MXD map (sample : 1 shapefile of world countries)
                this.LoadMyMXDMap();

                // Initialize the Timer
                this.InitializeMyTimer();
        }

        private void BtnStartMyTimer_Click(object sender, EventArgs e)
        {
            timer1.Start();
        }

        ...

        private void InitializeMyTimer()
        {
            timer1.Interval = 1000;
        }

        private void Timer1_Tick(object sender, EventArgs e)
        {
                // Stop the Timer before drawing
                timer1.Stop();

                // Use the Graphic Tracker Controler to perform a new drawing of 10000 points
                if (this.graphicTrackerControler != null)
                {
                    // Try a clean dispose & release of all COM objects
                    // MEMORY LEAK must come from this Method ??
                    this.graphicTrackerControler.DisposeGraphicTracker();
                }

                // Initialize new Graphic Tracker Controler and necessary objects
                this.graphicTrackerControler = new GraphicsControler();
                this.graphicTrackerControler.InitializeGraphicTracker();

                // Draw on Graphic Trackers 10000 point's geometries
                this.graphicTrackerControler.DrawPointsOnGraphicTracker();

                // Restart the Timer after drawing
                timer1.Start();
        }

        private void LoadMyMXDMap()
        {
                // my MXD doc map
                string mxdFilePath = @"C:\my_maps\WORLD.mxd";

                IMapDocument mapDocument = new MapDocumentClass();
                mapDocument.Open(mxdFilePath);

                // Display the map on Map Control
                Form1.CurrentMap = mapDocument.get_Map(0);
                this.axMapControl.Map = Form1.CurrentMap;
        }
    }


one Class "GraphicsControler" which manage the Graphic Tracker (initialize, dispose, draw) and added geometries
    public class GraphicsControler
    {
        /// <summary> Graphic Tracker
        /// </summary>
        private IGraphicTracker graphicTrackerLayer;

        /// <summary> List of Geometries added to the Graphic Tracker
        /// </summary>
        private List<IGeometry> listOfGeometries;

        /// <summary> Symbol for Point's geometries on the Graphic Tracker
        /// </summary>
        private IGraphicTrackerSymbol symbolForPoints;

        public void DrawPointsOnGraphicTracker()
        {
            try
            {
                if (this.graphicTrackerLayer != null)
                {
                    // Disable graphic tracker auto-refresh
                    this.graphicTrackerLayer.SuspendUpdate = true;

                    IGeometry geometry;
                    IPoint point;
                    double coordX = 500;
                    double coordY = 5000;

                    // Add 10000 point geometries to the Graphic Tracker
                    for (int i = 0; i < 10000; i++)
                    {
                        coordX = coordX + 500;
                        coordY = coordY + 600;

                        point = new PointClass();
                        point.PutCoords(coordX, coordY);
                        geometry = point as IGeometry;

                        // Add the geometry to the graphic tracker
                        this.graphicTrackerLayer.Add(geometry, this.symbolForPoints);

                        // Preserve the added geometry for future COM release
                        this.listOfGeometries.Add(geometry);
                    }

                    // Enable graphic tracker auto-refresh
                    this.graphicTrackerLayer.SuspendUpdate = false;
                }
            }
            catch (Exception exc)
            {
                MessageBox.Show(exc.Message, "DrawPointsOnGraphicTracker");
            }
        }

        public void InitializeGraphicTracker()
        {
            try
            {
                this.graphicTrackerLayer = new GraphicTrackerClass();
                this.graphicTrackerLayer.Initialize(Form1.CurrentMap as IBasicMap);

                // Create one Symbol for the added points
                this.CreateGraphicTrackerSymbolForPoints();

                this.listOfGeometries = new List<IGeometry>();
            }
            catch (Exception exc)
            {
                MessageBox.Show(exc.Message, "InitializeGraphicTracker");
            }
        }

        public void DisposeGraphicTracker()
        {
            try
            {
                // MEMORY LEAK must come from this Method ??
                if (this.listOfGeometries != null)
                {
                    if (this.listOfGeometries.Count > 0)
                    {
                        // Release COM for each Geometry added to the Graphic Tracker
                        foreach (IGeometry item in this.listOfGeometries)
                        {
                            item.SetEmpty();
                            this.CompleteReleaseOfCOMObject(item);
                        }

                        this.listOfGeometries.Clear();
                    }
                }

                if (this.graphicTrackerLayer != null)
                {
                    // Disable graphic tracker auto-refresh
                    this.graphicTrackerLayer.SuspendUpdate = true;
                                        
                    // Delete all geometries added to the Graphic Tracker
                    //  this method seams to clean the Graphic Tracker, without releasing memory
                    this.graphicTrackerLayer.RemoveAll();

                    // Enable graphic tracker auto-refresh
                    this.graphicTrackerLayer.SuspendUpdate = false;
                }

                // Release my Symbol
                this.CompleteReleaseOfCOMObject(this.symbolForPoints);

                // Release my Graphic Tracker
                this.CompleteReleaseOfCOMObject(this.graphicTrackerLayer);
            }
            catch (Exception exc)
            {
                MessageBox.Show(exc.Message, "DisposeGraphicTracker");
            }
        }

        private void CreateGraphicTrackerSymbolForPoints()
        {
            try
            {
                if (this.graphicTrackerLayer != null)
                {
                    ICharacterMarkerSymbol characterMarkerSymbol;
                    stdole.IFontDisp symbolFont = new stdole.StdFontClass() as stdole.IFontDisp;
                    symbolFont.Name = "ESRI Default Marker";

                    characterMarkerSymbol = new CharacterMarkerSymbolClass();
                    characterMarkerSymbol.Font = symbolFont;
                    characterMarkerSymbol.Color = new RgbColorClass() { Red = 0, Green = 0, Blue = 0 };
                    characterMarkerSymbol.CharacterIndex = 86;
                    characterMarkerSymbol.Size = 10;

                    this.symbolForPoints = this.graphicTrackerLayer.CreateSymbol(characterMarkerSymbol as ISymbol, null);
                }
            }
            catch (Exception exc)
            {
                MessageBox.Show(exc.Message, "CreateGraphicTrackerSymbolForPoints");
            }
        }

        private void CompleteReleaseOfCOMObject(object objetALiberer)
        {
            try
            {
                ComReleaser.ReleaseCOMObject(objetALiberer);

                if (objetALiberer != null)
                {
                    int refsLeft = 0;
                    do
                    {
                        refsLeft = Marshal.ReleaseComObject(objetALiberer);
                    }
                    while (refsLeft > 0);
                }
            }
            catch (Exception exc)
            {
                MessageBox.Show(exc.Message, "CompleteReleaseOfCOMObject");
            }
        }
    }


Thanks in advance for any help !

complete source code in .zip is attached.

Outcomes