ArcEngine 导出图片内存泄露问题

private Image ExportMap(IEnvelope pEnvelope, int width, int height)
{
IExport export = GetMapExport(TileParameter2.StorageInfo.Format.ToString().ToLower(), _backColor, (short)TileParameter2.StorageInfo.CompressionQuality);
                        //export as IP.BackgroundColor = _backColor;
                        //export.TransparentColor = _backColor;
                        //export.ImageType = esriExportImageType.esriExportImageTypeTrueColor;
                        export.Resolution = 96;
                        string folder = Application.StartupPath + "\\tmp";
                        if (!System.IO.Directory.Exists(folder))
                        {
                            System.IO.Directory.CreateDirectory(folder);
                        }
                        string tmpFileName = folder + "\\" + Guid.NewGuid().ToString() + ".png";
                        export.ExportFileName = tmpFileName;
                        IEnvelope pixelBounds = new EnvelopeClass();
                        pixelBounds.XMin = exportRect.left;
                        pixelBounds.XMax = exportRect.right;
                        pixelBounds.YMin = exportRect.top;
                        pixelBounds.YMax = exportRect.bottom;
                        export.PixelBounds = pixelBounds;
                        int hdc = export.StartExporting();
                        _activeView.Output(hdc, DPI, ref exportRect, pEnvelope, null);
                        export.FinishExporting();
                        export.Cleanup();

                        ReleaseComObject(pixelBounds);
                        ReleaseComObject(export);

                        Bitmap image = new Bitmap(tmpFileName);
                        Image result = new Bitmap(image);
                        image.Dispose();

                        System.IO.File.Delete(tmpFileName);
                        return result;
}
 
上面是使用IActiveView导出特定位置图片的函数代码。 经过反复测试发现,批量执行该函数会导致内存泄露的问题,即内存会一致增长(返回的Image我已经释放过了)。对于这个内存泄露的问题,想了很多方法(比如_activeView.ScreenDisplay.RemoveAllCaches();释放缓存;强制刷新_activeView.ScreenDisplay.Invalidate(null, true, _activeView.ScreenCacheID[esriViewDrawPhase.esriViewAll, null]);等),都不见效,是不是AE的Bug? 我的版本是10.1的。
 
感谢几位大牛的回复,之前贴出的代码不完整,不好意思,下面是完整的代码:
        private void ExportMap(IEnvelope pEnvelope, int width, int height)
        {
            //初始化Export对象
            tagRECT exportRect;
            exportRect.left = 0;
            exportRect.top = 0;
            exportRect.bottom = height;
            exportRect.right = width;
            ExportPNGClass export = new ExportPNGClass();
            export.ImageType = esriExportImageType.esriExportImageTypeTrueColor;
            IColor backColor = new RgbColorClass()
            {
                Red = 0,
                Green = 0,
                Blue = 0
            };
            export.BackgroundColor = backColor;
            export.TransparentColor = backColor;
            export.Resolution = 96;
            string folder = Application.StartupPath + "\\tmp";
            if (!System.IO.Directory.Exists(folder))
            {
                System.IO.Directory.CreateDirectory(folder);
            }
            string tmpFileName = folder + "\\" + Guid.NewGuid().ToString() + ".png";
            export.ExportFileName = tmpFileName;
            IEnvelope pixelBounds = new EnvelopeClass();
            pixelBounds.XMin = exportRect.left;
            pixelBounds.XMax = exportRect.right;
            pixelBounds.YMin = exportRect.top;
            pixelBounds.YMax = exportRect.bottom;
            export.PixelBounds = pixelBounds;

            //开始导图
            int hdc = export.StartExporting();
            _activeView.Output(hdc, DPI, ref exportRect, pEnvelope, null);
            export.FinishExporting();
            export.Cleanup();
            //清理AE对象
            ReleaseComObject(pixelBounds);
            ReleaseComObject(export);

            //清理临时文件
            System.IO.File.Delete(tmpFileName);
        }
 
测试发现,如果一直导出相同位置的图片,内存增长若干次后就不再增多了;但是如果导出的是不同比例尺下不同为主的图片,内存就一直在增长,增长速度不是很快,大概10分钟增长20M左右内存。 附图是带有创建与释放图片内存的函数执行,使用Windows自带perfmon工具监视的结果。图中部分位置非托管内存很小是因为处于调试状态,触发了断点;部分时刻的瞬时内存很高,是因为初始化了Image对象,然后又释放掉了。从图上可以看出从整体上看非托管内存是持续增长的。 图中左侧单位是100KB,也就是说内存在约1110000KB至116000KB之间。
 
初步怀疑是Export对象导出的过程,导致地图产生了缓存,而缓存又一直没有释放导致的,但是在每次函数执行后调用_activeView.ScreenDisplay.RemoveAllCaches();发现没有效果,事实上_activeView.ScreenDisplay.CacheCount大部分时候都是0。如果真是缓存的原因,我怀疑要么是AE10.1的Bug,要么是有某个函数能清理掉缓存,但是我不知道应该调用哪个函数。
 
感谢各位大牛的帮助,谢谢!
非托管内存增长图.gif
已邀请:

YoungHappy

赞同来自:

用GC.Collect()试试管用否?

灰太郞

赞同来自:

不管用,可以确定是非托管资源导致的内存溢出问题,然后通过进一步调试确认就是AE对象的内存释放问题。

石羽

赞同来自:

批量执行的话,Export不用每次都new了吧,又建有删的多麻烦。
如果是测试bug,image跟arcgis没关系,可以放到循环外面吧。删除也是。
另外,int width, int height都没用上啊,exportRect又是从哪来得?好吧,这应该与问题无关,只是影响阅读。
最后再试试,注意垃圾回收啊。

朱新颖

赞同来自:

如果需要测试的话建议您把代码简化,完整代码贴出来,详细描述一下如何再现该问题。

呆呆瓜小司 - 80后it男

赞同来自:

地地图的图层用的符号或render有自己扩展的么?如果有的话,可能是实现上有问题。

要回复问题请先登录注册