三维GIS交流 WorldWind GoogleEarth EV-Globe osgearth


               积沙成塔,集腋成裘,千里之行,积于跬步。夏丏尊有联:贵有恒,何必三更起五更睡;最无益,只怕一日曝十日寒。

  博客园 :: 首页 :: 博问 :: 闪存 :: 新随笔 :: 联系 :: 订阅 订阅 :: 管理 ::
http://www.gisforum.net/bbs/dispbbs.asp?boardID=20&ID=89985&page=1

.net中使用com对象,使用后必须通过如下代码释放:
比如定义的solayer类型的变量objlayer
System.Runtime.InteropServices.Marshal.ReleaseComObject(objlayer);
objlayer=null;
如果接口返回值也是一个com对象的话,也必须定义一个变量来接收,然后释放:
比如:
object handle;
handle=superworkspace1.CtlHandle();
supermap1.Connect(handle);
System.Runtime.InteropServices.Marshal.ReleaseComObject(handle);
handle=null;

superxll 其实已经说的比较清楚了,我补充一下:

在.NET中,当调用unmanaged COM组件的时候,它实际上是间接地通过RCW(Runtime Callalbe Wrapper)进行的,所以,我们在调用的时候,要遵循一些规范。对于从unmanaged COM组件返回的对象,我们要对其调用 System.Runtime.InteropServices.Marshal.ReleaseComObject()方法并将其设为null,才能将 其正确释放,并保证其正常运作。特别是,对于一些隐含返回的对象,也要这样调用。有三种典型的用法需要注意。

1,普通使用
SuperMapLib.soStyle objStyle;
objStyle = new SuperMapLib.soStyle
..//use this object

System.Runtime.InteropServices.Marshal.ReleaseComObject(objStyle);
objStyle = null;

2,中间临时对象


SuperMapLib.soDataSource soDs;
SuperMapLib.soDataset sodt;
...//get datasource

..//get dataset
//sodt = soDs.Datasets[1]; 这种写法不对
//正确的写法是:
SuperMapLib.soDatasets sodts;
sodts = soDs.Datasets;
sodt = sodts[1];


// ... use dataset

//release objects now.
System.Runtime.InteropServices.Marshal.ReleaseComObject(sodt);
sodt = null;

System.Runtime.InteropServices.Marshal.ReleaseComObject(sodts);
sodts = null;

System.Runtime.InteropServices.Marshal.ReleaseComObject(soDs);
soDs = null;

原因是这个soDatasets对象也已经隐含的被放到manager code中了,如果没有调用
System.Runtime.InteropServices.Marshal.ReleaseComObject()方法,这些对象将停
留在.net运行空间内,.net的垃圾收集器会多次去回收她。


3,返回型临时变量

这种类型的一个典型调用是soLayers.AddDataset()方法。

根据上面第二点,我们先得到soLayers;
SuperMapLib.soLayers objLayers;
objLayers = axSuperMap1.Layers;

SuperMapLib.soDataset objdt;

//...get the dataset
//objdt = ...

//这种写法不对: objLayers.AddDataset(objdt,true);
//正确的写法是:
SuperMapLib.soLayer tempLayer;
tempLayer = objLayers.AddDataset(objdt,true);

System.Runtime.InteropServices.Marshal.ReleaseComObject(tempLayer);
tempLayer = null;

原理与第二点差不多,因为已经有一个soLayer被隐含的放在.net运行空间中了,需要
显式的释放它。

更多的详细信息,可以参考msdn中System.Runtime.InteropServices.Marshal.ReleaseComObject()方法的说明。
大家可能感到这样使用不太方便,但目前确实需要这样编写才能够在.net中使用。这个也不是SuperMap Objects特有的问题,所有的COM对象都有相同的特点要求。我们衷心的希望微软能够改进垃圾回收器,更加智能的帮助开发人员释放对象。


posted on 2007-09-08 11:34  niceboy  阅读(564)  评论(0编辑  收藏  举报
点击这里给我发消息