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,要么是有某个函数能清理掉缓存,但是我不知道应该调用哪个函数。
感谢各位大牛的帮助,谢谢!
{
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,要么是有某个函数能清理掉缓存,但是我不知道应该调用哪个函数。
感谢各位大牛的帮助,谢谢!
6 个回复
YoungHappy
赞同来自:
灰太郞
赞同来自:
石羽
赞同来自:
如果是测试bug,image跟arcgis没关系,可以放到循环外面吧。删除也是。
另外,int width, int height都没用上啊,exportRect又是从哪来得?好吧,这应该与问题无关,只是影响阅读。
最后再试试,注意垃圾回收啊。
朱新颖
赞同来自:
呆呆瓜小司 - 80后it男
赞同来自:
要回复问题请先登录或注册
发起人
相关问题
问题状态