Select to view content in your preferred language

memory leak in mapcontrol

3439
6
05-15-2011 01:14 AM
haowoo1
Emerging Contributor
Hello all, I'm using dynamic mode to draw polylines in the mapcontrol, the codes are as follows. After running the program, the lines are drawn, but I found the memory was increasing all the time, anyone please help me to find the issue? thanks!

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using ESRI.ArcGIS.Controls;
using ESRI.ArcGIS.Carto;
using ESRI.ArcGIS.Display;
using ESRI.ArcGIS.Geometry;
using ESRI.ArcGIS.esriSystem;

namespace MapMemTest
{
    public partial class Form1 : Form
    {
        IMapControl4 m_mapControl = null;
        Timer stoptimer = new Timer();
        private IMap m_map;
        private IActiveView m_activeView;
        private IDisplay m_display;

        private IDynamicMap m_dynamicMap = null;
        private bool m_bIsDynamicMode = false;
        protected object Missing = Type.Missing;

        public Form1()
        {
            InitializeComponent();

            Init();
        }

        void Init()
        {
            m_mapControl = axMapControl1.Object as IMapControl4;
            m_mapControl.Extent = m_mapControl.FullExtent;
          
            m_activeView = m_mapControl.Map as IActiveView;
            m_dynamicMap = m_mapControl.Map as IDynamicMap;
            if (!m_bIsDynamicMode)
            {
                //switch into dynamic mode
                if (!m_dynamicMap.DynamicMapEnabled)
                    m_dynamicMap.DynamicMapEnabled = true;

                //start listening to DynamicMap's 'After Draw' events
                ((IDynamicMapEvents_Event)m_dynamicMap).AfterDynamicDraw +=
                    new IDynamicMapEvents_AfterDynamicDrawEventHandler(Form1_AfterDynamicDraw);
            }

            stoptimer.Enabled = true;
            stoptimer.Interval = 500;
            stoptimer.Tick += new EventHandler(stoptimer_Tick);
        }

        void Form1_AfterDynamicDraw(esriDynamicMapDrawPhase DynamicMapDrawPhase, IDisplay Display, IDynamicDisplay dynamicDisplay)
        {
            if (esriDynamicMapDrawPhase.esriDMDPDynamicLayers != DynamicMapDrawPhase)
                return;
            DrawLineMemTest(dynamicDisplay);

        }

        void DrawLineMemTest(IDynamicDisplay dynamicDisplay)
        {
            IPointCollection4 pointcoll0 = new PolylineClass();
            IPoint p0 = new PointClass();
         
            List<IPoint> tmppoints = new List<IPoint>();           
            int pointcount = 1801;
            WKSPoint[] points = new WKSPoint[pointcount];

            int tmpcount = 0;
            for (double i = -90; i < 90; i += 0.1)
            {
                WKSPoint wksp;
                wksp.X = i;
                wksp.Y =i;

                points[tmpcount] = wksp;
                tmpcount++;
            }

            IGeometryBridge2 pGeoBri = new GeometryEnvironmentClass();
            pGeoBri.AddWKSPoints(pointcoll0,ref points);

            DynamicDrawLine(pointcoll0, 230, 0, 0, 2, dynamicDisplay);
          
        }

        void stoptimer_Tick(object sender, EventArgs e)
        {
           m_activeView.PartialRefresh(esriViewDrawPhase.esriViewGeography, null, null);
        }

        void DynamicDrawLine(IPointCollection linePointColl, byte r, byte g, byte b,
          double width, IDynamicDisplay dynamicDisplay)
        {
            m_dynamicSymbolProps = dynamicDisplay as IDynamicSymbolProperties2;
            m_dynamicSymbolProps.SetScale(esriDynamicSymbolType.esriDSymbolLine, (float)width, (float)width);
            m_dynamicSymbolProps.SetColor(esriDynamicSymbolType.esriDSymbolLine, (float)r / 255, (float)g / 255, (float)b / 255, 1.0f);
         
            dynamicDisplay.DrawPolyline(linePointColl);
        }
    }
}
0 Kudos
6 Replies
UjjwalNigam
Regular Contributor
Hi,
Did you try using COMReleaser as the last line of code in the Tick event?
It seems you are continuously "building up" memory by not garbage collecting the previous objects.
0 Kudos
haowoo1
Emerging Contributor
Hi,
Did you try using COMReleaser as the last line of code in the Tick event?
It seems you are continuously "building up" memory by not garbage collecting the previous objects.


thanks, I tried to add "ESRI.ArcGIS.ADF.ComReleaser.ReleaseCOMObject(pointcoll0);"  behind "DynamicDrawLine(pointcoll0, 230, 0, 0, 2, dynamicDisplay);"  in the function DrawLineMemTest(), but the memory is still increasing, is there any other objects need to be released?
0 Kudos
RichardWatson
Deactivated User
If you want to figure out what is leaking then you can use a tool like SysInternals VMMap to capture the call stacks.  A commerical tool such as http://www.red-gate.com/products/dotnet-development/ants-memory-profiler/ is even better.

If the objects which are leaking are COM objects then search on Marshal.ReleaseComObject.  There has been a lot of discussion about this.  The issue is that .NET Garbage Collection does not have any idea how much memory a COM object uses so it does not work well.
0 Kudos
haowoo1
Emerging Contributor
If you want to figure out what is leaking then you can use a tool like SysInternals VMMap to capture the call stacks.  A commerical tool such as http://www.red-gate.com/products/dotnet-development/ants-memory-profiler/ is even better.

If the objects which are leaking are COM objects then search on Marshal.ReleaseComObject.  There has been a lot of discussion about this.  The issue is that .NET Garbage Collection does not have any idea how much memory a COM object uses so it does not work well.


I'm sure that is cased by this method "dynamicDisplay.DrawPolyline(linePointColl);", after comment it, the memory stays still, any ideas about it?
0 Kudos
haowoo1
Emerging Contributor
I think I have found the problem, since it is a multi-thread program, the polyline was created in every drawing circle, and these COM objects seems hard to release in the multi-thread program, so the memory increases all the time. So I set the polyline as a global variable and update the points with IGeometryBridge2 rather than clear and add points again, then during every drawing circle, the points in the polyline were just updated, no more COM objects are created, after these changes, the memory stop increasing and  returns to normal.
0 Kudos
RichardWatson
Deactivated User
ArcObjects work on a threading model which ESRI refers to as threads in isolation which is a fancy way of saying that they are all singled threaded.  All calls to ArcObjects are marshalled to the thread which created the object.  The way that Windows actually does that is it uses windows messages (think Spy++) and when those messages are dispatched the call occurs on the creation thread.

COM itself supports threading just fine and has no problem releasing.
0 Kudos