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条数据,也可以通过测试)。相当于解决“超出打开游标最大数”的问题时,顺带着让另一个问题也消灭了(可能是我不理解期间的具体原理,有待深入)。

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

时间: 2024-10-27 12:57:24

C#+ArcEngine中com对象的释放问题的相关文章

ArcEngine中COM对象与其基础RCW分开后就不能再使用

操作ArcEngine中的COM对象时,为了减少内存的增长,用掉的对象要手动释放常用的方法是ReleaseComObject System.Runtime.InteropServices.Marshal.ReleaseComObject(relObj); 但有时会报"COM对象与其基础RCW分开后就不能再使用"错误.这是因为对象被释放了,再去引用就找不到了,所在释放对象固然好,但要分清楚.

ArcEngine中Feature对象的Shape属性和ShapeCopy属性

1.ShapeCopy只读属性是对要素Shape属性的复制,当修改一个要素或要素集的时候,用ShapeCopy属性获取一个要素的Shape,然后进行几何形状的修改.2.Shape典型的应用:a.通过ShapeCopy属性获取一个要素的的几何形状:b.修改获得的几何形状:c.利用IFeature.Shape设置要素的几何形状Geometryd.保存要素

在程序运行过程中,对象所占的空间是不能随时释放的

使用类名定义的对象(请查看:C++类的声明和对象的定义)都是静态的,在程序运行过程中,对象所占的空间是不能随时释放的.但有时人们希望在需要用到对象时才建立对象,在不需要用该对象时就撤销它,释放它所占的内存空间以供别的数据使用.这样可提高内存空间的利用率. 在C++中,可以使用new运算符动态地分配内存,用delete运算符释放这些内存空间(请查看:C++动态分配内存(new)和撤销内存(delete)).这也适用于对象,可以用new运算符动态建立对象,用delete运算符撤销对象. 如果已经定义

检查SharePoint代码中对象是否释放的小工具

问题 一般继承IDisposable接口的对象, 在使用完成后可以释放对象以免占用过多的资源, 当然也可是使用using语句来完成此操作. 但是当项目很大的时候, 代码也比较多, 我们更多希望有工具来检查项目中是否有类似的对象没有释放. 解决办法 微软其实提供了一个小工具"SharePoint Dispose Checker Tool", 但是很遗憾, 不支持SharePoint 2013, 有需求的朋友可以点击下面的链接查看. 地址: https://gallery.technet.

js中window对象详解以及页面跳转

js中window对象详解以及页面跳转 转自:http://www.makaidong.com/%E5%8D%9A%E5%AE%A2%E5%9B%AD%E6%90%9C/39219.shtml 1.window.top.window.location = "index.asp"; 2.window.top.location.href="index.asp" 3. window.top.location.replace("index.asp");

C++中堆对象的构造函数和析构函数逆向分析

实验环境: 操作系统:Windows XP Professional Service Pack 3 集成开发环境:Microsoft Visual C++ 6.0 构建版本:Debug版本 实验代码: 1 #include <stdio.h> 2 3 class People 4 { 5 public: 6 People() { printf("Constructor!\n"); } 7 ~People() { printf("Destructor!\n"

(转)深入理解JavaScript的闭包特性 如何给循环中的对象添加事件

深入理解JavaScript的闭包特性如何给循环中的对象添加事件 初学者经常碰到的,即获取HTML元素集合,循环给元素添加事件.在事件响应函数中(event handler)获取对应的索引.但每次获取的都是最后一次循环的索引.原因是初学者并未理解JavaScript的闭包特性. 有个网友问了个问题,如下的html,为什么点击所有的段落p输出都是5,而不是alert出对应的0,1,2,3,4. 1.  <!DOCTYPE HTML> 2.  <html> 3.  <head&g

理解HTML5中Range对象

1.理解Range对象    重新来学习下HTML5中的Range对象和Selection对象,最近在维护富文本编辑器,感觉这方面的知识点很有用,所以趁着周末多学习下~  什么是Range对象? 在HTML5中,一个Range对象代表页面上的一段连续区域.可以通过如下语句创建一个空的Range对象.如下代码: var range = document.createRange(); 什么是Selection对象? 在HTML5中,每一个浏览器窗口都有一个Selection对象,代表用户鼠标在页面中

C#中Monitor对象与Lock关键字的区别分析

这篇文章主要介绍了C#中Monitor对象与Lock关键字的区别,需要的朋友可以参考下 Monitor对象 1.Monitor.Enter(object)方法是获取 锁,Monitor.Exit(object)方法是释放锁,这就是Monitor最常用的两个方法,当然在使用过程中为了避免获取锁之后因为异常,致锁 无法释放,所以需要在try{} catch(){}之后的finally{}结构体中释放锁(Monitor.Exit()).2.Monitor的常用属性和方法: Enter(Object)