Arcgis Engine开发在Scenecontrol上添加text动态更新时内存不断增长 arcgis三维内存 解决方案 » 免费领取超大流量手机卡,每月29元包185G流量+100分钟通话, 中国电信官方发货 涨到了1G多还在增长,界面已经卡的不能工作了。你的物理内存都用光了吗?如果没有用光,那么你得“卡”就不是内存问题(而是你程序UI线程或者整个CPU占用问题),相反这个时候就不应该花时间去释放内存。 线程操作有没有用invoke委托? 涨到了1G多还在增长,界面已经卡的不能工作了。你的物理内存都用光了吗?如果没有用光,那么你得“卡”就不是内存问题(而是你程序UI线程或者整个CPU占用问题),相反这个时候就不应该花时间去释放内存。没有用完,我2g的,用到1g多的时候,我UI还是可以操作,但是当操作界面的时候(我理解每次操作都相当于让界面刷新),都会出现“卡”的情况,就是当我滑动三维控件,从原始位置直接到了最终位置。我理解这个是卡。程序还在增长内存,这是为什么呢,我的CPU才不到10%,UI上面一直执行的都是刷新线程。 当然有用,之前是用system.timers.timer用的委托,后来试过system.windows.form.timer,这定时器是可以直接操作UI的 涨到了1G多还在增长,界面已经卡的不能工作了。你的物理内存都用光了吗?如果没有用光,那么你得“卡”就不是内存问题(而是你程序UI线程或者整个CPU占用问题),相反这个时候就不应该花时间去释放内存。比如这段代码using System;using System.Collections.Generic;using System.ComponentModel;using System.Data;using System.Drawing;using System.Linq;using System.Text;using System.Threading.Tasks;using System.Windows.Forms;using System.IO;using System.IO.Ports;using System.Runtime.InteropServices;using System.Threading;using ESRI.ArcGIS.esriSystem;using ESRI.ArcGIS.Carto;using ESRI.ArcGIS.Controls;using ESRI.ArcGIS.ADF;using ESRI.ArcGIS.SystemUI;using ESRI.ArcGIS.Geodatabase;using ESRI.ArcGIS.DataSourcesFile;using ESRI.ArcGIS.Geometry;using ESRI.ArcGIS.Analyst3D;using ESRI.ArcGIS.Display;using ESRI.ArcGIS.GlobeCore;namespace WindowsFormsApplication3{ public partial class Form1 : Form { public Form1() { InitializeComponent(); InitTimer(); text3DElement = new Text3DElementClass(); graphicsLayer = new GraphicsLayer3DClass(); Init3DText(); } System.Windows.Forms.Timer Updatetimer; IGraphicsLayer graphicsLayer;//将graphics图层定义为全局,就这么一个图层 IText3DElement text3DElement;//同上,将这个3delement也定义为全局 IGraphicsContainer3D graphicsContainer3D;//这个也是 int i = 0; public void InitTimer() { Updatetimer = new System.Windows.Forms.Timer(); Updatetimer.Interval = 100;//定时器时间设为100ms,直观看到内存的增长。 Updatetimer.Tick += new EventHandler(Updatetimer_Tick); } public void Init3DText() { graphicsContainer3D = graphicsLayer as IGraphicsContainer3D; text3DElement.FontName = "name"; text3DElement.Text = "开始"; text3DElement.AnchorPoint.X = 0; text3DElement.AnchorPoint.Y = 0; text3DElement.AnchorPoint.Z = 0; text3DElement.Depth = 0.5; text3DElement.Height = 2; text3DElement.Height = 2; text3DElement.BoldFont = true; text3DElement.RotationAngle = 360; ISimpleFillSymbol simpleFillSymbol = new SimpleFillSymbol(); IRgbColor color = new RgbColorClass(); color.Red = 255; simpleFillSymbol.Color = color; IFillShapeElement fillShapeElement = text3DElement as IFillShapeElement; fillShapeElement.Symbol = simpleFillSymbol as IFillSymbol; graphicsContainer3D.AddElement(text3DElement as IElement); text3DElement.Update();//这里如果不添加update就显示不出来了 this.axSceneControl1.Scene.AddLayer(graphicsLayer as ILayer); this.axSceneControl1.SceneGraph.Invalidate(graphicsLayer, true, false); this.axSceneControl1.SceneGraph.RefreshViewers(); } int num = 0; public void Updatetimer_Tick(object sender, EventArgs e) { i++; string text = text3DElement.Text; text = "是" + i;//还有这儿,如果我什么都不改,光update,当然是内存不变,就是说把这句删掉,不变 text3DElement.Text = text;//我就改了一下text涨这么厉害 text3DElement.Update();//内存飙升啊,就这句话 num = graphicsContainer3D.ElementCount;//这里看了下,graphicsContainer3D的确一直只有一个element存在 this.axSceneControl1.SceneGraph.Invalidate(graphicsLayer, true, false); this.axSceneControl1.SceneGraph.RefreshViewers(); GC.Collect();//这儿除了这句话,我也不知道有啥可释放的了, } private void button_Referesh_Click(object sender, EventArgs e) { Updatetimer.Start();//button,开启100ms定时器刷新 } private void button1_Click(object sender, EventArgs e) { text3DElement.Update();//单纯想看看这句话到底怎么回事,狂点五百多下button以后发现,涨一会儿,停一会儿,但是比修改text3delement肯定好多了 } private void button2_Click(object sender, EventArgs e) { while(true)//死循环,哗哗的涨啊 { i++; string text = text3DElement.Text; text = "是" + i; text3DElement.Text = text; text3DElement.Update(); num = graphicsContainer3D.ElementCount; this.axSceneControl1.SceneGraph.Invalidate(graphicsLayer, true, false); this.axSceneControl1.SceneGraph.RefreshViewers(); GC.Collect(); } } }}这是我写的测试程序,里面涉及到arcgis一些控件。 没看到任何一句Dispose(),却看到了GC.Collect();这就好像你通知清洁工倒垃圾,但是垃圾桶里其实什么都没放进去,东西都拿在你自己手上,那么清洁工不可能从你手上抢你正看的文件丢掉,你通知她来打扰你,反而耽误了你的正常工作不要在循环里执行GC.Collect(),这没啥意义 值类型的对象不存在"释放"的问题只有引用类型的对象需要释放而引用类型又分为托管的和非托管的,托管的不用你手动执行释放,没有对象去引用它了,GC就会负责回收它而非托管资源需要你主动告知哪些是可以释放的(使用Dispose)其实GC就好比清洁工,托管资源就类似苹果核,瓜子皮,烟头这些东西,一看就知道是不是需要丢掉而非托管资源就是写了字的纸,你不丢进垃圾桶,没人敢随便扔掉的 接上文,GC.Collect()就是通知清洁工可以进行清理了它不代表清洁工就马上会来,但是总是比不知道他什么时候有心情了来一趟要快一些就是了清洁工什么时候开始清理呢?定时清理;空间不足时清理那么很显然的,定时的时间和空间不足的剩余量,这些肯定会和你空间总大小是有关的如果你内存足够大,就不需要清理的太频繁,清理太频繁反而吃CPU,降低效率 但是现在的情况是,就这段代码,我的电脑4g内存2.18g可用,运行起来以后,一直占用物理内存到1.3g左右的时候,程序界面就死了。就相当于是直接未响应了。根本没有内存释放这个现象,这样不对吧?可是我也实在看不出来有什么dispose 的,我都定义的全局的。我把这段代码发给esri公司了,我感觉是这个text3delement.update();函数造成不自动释放的。 我感觉你的内存偏小,我做arcgis engine开发,去年是4G内存,做数据生产或数据质量检查的时候,或者加载mxd中地形图多点,就很慢。后来内存升到16G,装64位win7,再做上面同样的操作,速度快很多。个人感觉arcgis做图像、数据处理的时候就消耗内存多。 恩,看来我的确需要换个大点的试试,但是我的工程占用的物理内存急剧增长,为什么C#没有主动给我释放内存呢?是因为C#的内存管理机制认为还没必要释放内存,还是因为Arcgis engine创建的对象被scenecontrol引用所以没办法释放呢》? 你的内存常占用到80%左右,是么??arcgis本来就需要很多内存,就算你不做什么处理,也是。而且三维的占用内存就更多了。你可以试试写二维的文字,看看占用情况,再做分析。ArcGIS Engine开发中,一般cursor相关我都释放;using(ComReleaser pComReleaser=new ComReleaser()){ICursor queryCursor = queryTableSort.Rows; pComReleaser.ManageLifetime(queryCursor);}我现在采用这种释放资源的方式,是engine中自己的资源释放方式。但不是所有的都要释放。你如果用.net的释放方式:System.Runtime.InteropServices.Marshal.ReleaseComObject(queryCursor); System.GC.Collect();而且这种释放,尽量不要放在循环中。 明白了。我的内存到了92%-93%,程序就变得很卡,然后好像也不会再特别往上涨了。给esri发邮件问这个问题,美国那边说update就是会导致内存上涨,看来只有换个内存大的电脑了。 大家都来看看这几个小问题啊——很是纠结!!! 如何把大量数据以二进制形式存储到文件以及读取???大家都来看看 窗体设计不 问题? 如何在Access文件中用sql 语句创建数据表?在线等.. 有什么控件显示列表的时候可以从下往上的? 一个关于三维数组求求索引大小的问题??? 至少一个参数没有指定值 高手指點,此功能如何實現? 关于数据访问层DAL的问题,ado.net,大家提提看法 一个菜鸟问题,请大虾们拔刀相助! Winform程序打包安装后点击启动出现程序停止工作是怎么回事?clr20r3错误,求大神解答! C# 纯色图片如何随意更换其背景为其它图片
涨到了1G多还在增长,界面已经卡的不能工作了。你的物理内存都用光了吗?如果没有用光,那么你得“卡”就不是内存问题(而是你程序UI线程或者整个CPU占用问题),相反这个时候就不应该花时间去释放内存。
涨到了1G多还在增长,界面已经卡的不能工作了。你的物理内存都用光了吗?如果没有用光,那么你得“卡”就不是内存问题(而是你程序UI线程或者整个CPU占用问题),相反这个时候就不应该花时间去释放内存。没有用完,我2g的,用到1g多的时候,我UI还是可以操作,但是当操作界面的时候(我理解每次操作都相当于让界面刷新),都会出现“卡”的情况,就是当我滑动三维控件,从原始位置直接到了最终位置。我理解这个是卡。程序还在增长内存,这是为什么呢,我的CPU才不到10%,UI上面一直执行的都是刷新线程。
当然有用,之前是用system.timers.timer用的委托,后来试过system.windows.form.timer,这定时器是可以直接操作UI的
涨到了1G多还在增长,界面已经卡的不能工作了。你的物理内存都用光了吗?如果没有用光,那么你得“卡”就不是内存问题(而是你程序UI线程或者整个CPU占用问题),相反这个时候就不应该花时间去释放内存。
比如这段代码
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;using System.IO;
using System.IO.Ports;
using System.Runtime.InteropServices;
using System.Threading;using ESRI.ArcGIS.esriSystem;
using ESRI.ArcGIS.Carto;
using ESRI.ArcGIS.Controls;
using ESRI.ArcGIS.ADF;
using ESRI.ArcGIS.SystemUI;
using ESRI.ArcGIS.Geodatabase;
using ESRI.ArcGIS.DataSourcesFile;
using ESRI.ArcGIS.Geometry;
using ESRI.ArcGIS.Analyst3D;
using ESRI.ArcGIS.Display;
using ESRI.ArcGIS.GlobeCore;namespace WindowsFormsApplication3
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
InitTimer();
text3DElement = new Text3DElementClass();
graphicsLayer = new GraphicsLayer3DClass();
Init3DText();
}
System.Windows.Forms.Timer Updatetimer;
IGraphicsLayer graphicsLayer;//将graphics图层定义为全局,就这么一个图层
IText3DElement text3DElement;//同上,将这个3delement也定义为全局
IGraphicsContainer3D graphicsContainer3D;//这个也是
int i = 0;
public void InitTimer()
{
Updatetimer = new System.Windows.Forms.Timer();
Updatetimer.Interval = 100;//定时器时间设为100ms,直观看到内存的增长。
Updatetimer.Tick += new EventHandler(Updatetimer_Tick);
}
public void Init3DText()
{
graphicsContainer3D = graphicsLayer as IGraphicsContainer3D;
text3DElement.FontName = "name";
text3DElement.Text = "开始";
text3DElement.AnchorPoint.X = 0;
text3DElement.AnchorPoint.Y = 0;
text3DElement.AnchorPoint.Z = 0;
text3DElement.Depth = 0.5;
text3DElement.Height = 2;
text3DElement.Height = 2;
text3DElement.BoldFont = true;
text3DElement.RotationAngle = 360;
ISimpleFillSymbol simpleFillSymbol = new SimpleFillSymbol();
IRgbColor color = new RgbColorClass();
color.Red = 255;
simpleFillSymbol.Color = color;
IFillShapeElement fillShapeElement = text3DElement as IFillShapeElement;
fillShapeElement.Symbol = simpleFillSymbol as IFillSymbol;
graphicsContainer3D.AddElement(text3DElement as IElement);
text3DElement.Update();//这里如果不添加update就显示不出来了
this.axSceneControl1.Scene.AddLayer(graphicsLayer as ILayer);
this.axSceneControl1.SceneGraph.Invalidate(graphicsLayer, true, false);
this.axSceneControl1.SceneGraph.RefreshViewers();
} int num = 0; public void Updatetimer_Tick(object sender, EventArgs e)
{
i++;
string text = text3DElement.Text;
text = "是" + i;//还有这儿,如果我什么都不改,光update,当然是内存不变,就是说把这句删掉,不变
text3DElement.Text = text;//我就改了一下text涨这么厉害
text3DElement.Update();//内存飙升啊,就这句话
num = graphicsContainer3D.ElementCount;//这里看了下,graphicsContainer3D的确一直只有一个element存在
this.axSceneControl1.SceneGraph.Invalidate(graphicsLayer, true, false);
this.axSceneControl1.SceneGraph.RefreshViewers(); GC.Collect();//这儿除了这句话,我也不知道有啥可释放的了,
} private void button_Referesh_Click(object sender, EventArgs e)
{
Updatetimer.Start();//button,开启100ms定时器刷新
}
private void button1_Click(object sender, EventArgs e)
{
text3DElement.Update();//单纯想看看这句话到底怎么回事,狂点五百多下button以后发现,涨一会儿,停一会儿,但是比修改text3delement肯定好多了
} private void button2_Click(object sender, EventArgs e)
{
while(true)//死循环,哗哗的涨啊
{
i++;
string text = text3DElement.Text;
text = "是" + i;
text3DElement.Text = text;
text3DElement.Update();
num = graphicsContainer3D.ElementCount;
this.axSceneControl1.SceneGraph.Invalidate(graphicsLayer, true, false);
this.axSceneControl1.SceneGraph.RefreshViewers(); GC.Collect();
}
}
}
}
这是我写的测试程序,里面涉及到arcgis一些控件。
这就好像你通知清洁工倒垃圾,但是垃圾桶里其实什么都没放进去,东西都拿在你自己手上,那么清洁工不可能从你手上抢你正看的文件丢掉,你通知她来打扰你,反而耽误了你的正常工作不要在循环里执行GC.Collect(),这没啥意义
只有引用类型的对象需要释放而引用类型又分为托管的和非托管的,托管的不用你手动执行释放,没有对象去引用它了,GC就会负责回收它
而非托管资源需要你主动告知哪些是可以释放的(使用Dispose)其实GC就好比清洁工,托管资源就类似苹果核,瓜子皮,烟头这些东西,一看就知道是不是需要丢掉
而非托管资源就是写了字的纸,你不丢进垃圾桶,没人敢随便扔掉的
GC.Collect()就是通知清洁工可以进行清理了
它不代表清洁工就马上会来,但是总是比不知道他什么时候有心情了来一趟要快一些就是了清洁工什么时候开始清理呢?定时清理;空间不足时清理
那么很显然的,定时的时间和空间不足的剩余量,这些肯定会和你空间总大小是有关的
如果你内存足够大,就不需要清理的太频繁,清理太频繁反而吃CPU,降低效率
但是现在的情况是,就这段代码,我的电脑4g内存2.18g可用,运行起来以后,一直占用物理内存到1.3g左右的时候,程序界面就死了。就相当于是直接未响应了。根本没有内存释放这个现象,这样不对吧?可是我也实在看不出来有什么dispose 的,我都定义的全局的。我把这段代码发给esri公司了,我感觉是这个text3delement.update();函数造成不自动释放的。
后来内存升到16G,装64位win7,再做上面同样的操作,速度快很多。
个人感觉arcgis做图像、数据处理的时候就消耗内存多。
arcgis本来就需要很多内存,就算你不做什么处理,也是。
而且三维的占用内存就更多了。你可以试试写二维的文字,看看占用情况,再做分析。ArcGIS Engine开发中,一般cursor相关我都释放;
using(ComReleaser pComReleaser=new ComReleaser())
{
ICursor queryCursor = queryTableSort.Rows;
pComReleaser.ManageLifetime(queryCursor);
}我现在采用这种释放资源的方式,是engine中自己的资源释放方式。但不是所有的都要释放。你如果用.net的释放方式:
System.Runtime.InteropServices.Marshal.ReleaseComObject(queryCursor);
System.GC.Collect();而且这种释放,尽量不要放在循环中。
明白了。我的内存到了92%-93%,程序就变得很卡,然后好像也不会再特别往上涨了。给esri发邮件问这个问题,美国那边说update就是会导致内存上涨,看来只有换个内存大的电脑了。