C#+ArcEngine中com对象的释放问题

Posted 花火灬流年

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了C#+ArcEngine中com对象的释放问题相关的知识,希望对你有一定的参考价值。

1、问题描述

  最近在写C#下AE的开发,在循环获取数据并修改时碰到了两个问题“超出系统资源”和“超出打开游标最大数”;在网上看了一些资料,发现都是说在循环中没有释放已经使用过的对象,但是在循环中实际上是有为com对象赋值为null的,但是还是没法解决。后来想着将对象赋值为null和marshal是不是效果不一样,就特意写了一个简单的循环来测试,代码如下(初级代码,比较乱,请轻喷):

 1 public void Test_释放游标方式()
 2         {
 3             string ssName = "controlpoint";//图层名称(里面有4w多条数据)
         //测试两种释放方式的执行时间
4 DateTime tmStart = DateTime.Now; 5 DisplayString("开始于:"+tmStart.ToLongTimeString()+"\r\n"); 6 DateTime tmEnd; 7 DateTime tmMiddle1; 8 DateTime tmMiddle2; 9 TimeSpan ts, tsMax;
         //具体执行代码
10 IFeatureWorkspace pFeaWs = mc_Ws as IFeatureWorkspace;//我已经建立好的SDE工作空间对象 11 IFeatureClass pFeaCls = pFeaWs.OpenFeatureClass(ssName); 12 string strWhere = string.Format("stationserieseventid in (‘f9bd16ed-ae2a-454c-9eba-7123dc41af28‘,‘7e3d0d4a-8c5e-49b5-8977-e060cd4cef6d‘,‘a89300a5-3503-4976-b5d2-3d5a712f7b36‘)"); 13 IFeatureCursor pCur = null; 14 IFeature pFea = null; 15 IQueryFilter pFilter = new QueryFilterClass(); 16 int numCurHasBuild = 0; 17 //int counsts = pFeaCls.FeatureCount(null);//总要素个数 18 try 19 { 20 tmStart = DateTime.Now; 21 DisplayString("开始于:" + tmStart.ToLongTimeString()+"\r\n"); 22 tsMax = TimeSpan.MinValue;
23 int idxStart = 45809; 24 int idxEnd = 90416; 25 int idxTmpNode = idxStart + 1000 26 for (int idx = idxStart; idx < idxTmpNode; idx++) 27 { 28 tmMiddle1 = DateTime.Now; 29 strWhere = "objectid = ‘" + idx.ToString() + ""; 30 pFilter.WhereClause = strWhere;
             //获取游标对象
31 pCur = pFeaCls.Search(pFilter, false);//如果游标对象没有释放,那么一次循环不能超过280,否则会爆‘超出打开游标最大数’错误 32 numCurHasBuild++;
             //循环获取游标内的要素
33 pFea = pCur.NextFeature(); 34 while (pFea != null) 35 { 36 string tmp = pFea.get_Value(1).ToString(); 37 pFea = pCur.NextFeature(); 38 } 39 //pCur = null;//像这样,对象实际上是没有释放的;依旧会在283条的时候报错 40 Marshal.ReleaseComObject(pCur);//这种方式可以完全释放掉对象,此时可以完全循环完4w条数据 41 localReleaseComObj(pCur); 42 if (pCur != null) 43 localReleaseComObj(pCur);

45 tmMiddle2 = DateTime.Now; 46 ts = tmMiddle2 - tmMiddle1; 47 if (ts > tsMax) 48 tsMax = ts; 49 } 50 tmEnd = DateTime.Now; 51 DisplayString("循环中耗时最多的一次时间为:"+tsMax.TotalSeconds+"\r\n"); 52 DisplayString("执行完一轮循环;消耗的总时间为:"+(tmEnd-tmStart).TotalSeconds+"\r\n"); 53 } 54 catch (Exception ex) 55 { 56 DisplayString("在第" + numCurHasBuild.ToString() + "处发生错误!\r\n" + ex.Message); 57 throw new Exception(ex.Message); 58 } 59 }

2、试验过程

  在测试中,专门打开一个控制点图层(里面有4w多条数据),然后根据条件循环建立游标获取对象;

情况一:在使用完游标之后,将其赋值为null;这时候对象实际上是没有被释放掉的,因此在283次循环时就会报错‘ora 超出打开游标最大数’;

情况二:在使用完游标时,在循环末尾,用marshal.releasecomobject方法来释放com对象,这时循环可以走完4w次;我认为这时对象是完全被释放掉了的。

同时在使用marshal.releasecomobject方法时,并没有增加多余的时间,循环执行时间上还是跟不释放对象一样(小数据量比较)。

3、结论

  在使用ArcEngine中的游标对象时,一定要在使用完之后进行对象的释放,否则会不定时出现上面的错误;而且需要使用marshal.releasecomobject方法来进行对象的释放,赋值为null是达不到目的的;

  另外说一下“超出系统资源”的这个错误,这个在最初没有释放对象时,每次当数据量超过200就会不定时报这个错误,一直也没法解决;但是当我在循环中加上marshal.releasecomobject方法释放对象后,这个问题竟然莫名消失了(后来特意试了4000条数据,也可以通过测试)。相当于解决“超出打开游标最大数”的问题时,顺带着让另一个问题也消灭了(可能是我不理解期间的具体原理,有待深入)。

 

这个问题就暂时写这么多吧,等有深入了解了,再回来补充?!

以上是关于C#+ArcEngine中com对象的释放问题的主要内容,如果未能解决你的问题,请参考以下文章

ArcEngine真正释放锁文件,彻底移除图层

arcengine 怎么从sde数据库中查询得到feature对象

怎么用arcengine+c#在地图上实时显示网上传过来gps坐标点?

从 C++ 调用 C# com 对象,谁应该释放内存?

C#-ArcEngine 图层属性查询的部分代码

如何释放后期绑定的 COM 对象?