gisempire100
捉鬼专家
捉鬼专家
  • 注册日期2004-08-13
  • 发帖数552
  • QQ
  • 铜币2462枚
  • 威望0点
  • 贡献值0点
  • 银元0个
阅读:1756回复:2

.NET+AE开发中常见几种非托管对象的释放

楼主#
更多 发布于:2008-04-25 20:49
<P  align=center><STRONG>.</STRONG><STRONG>NET+AE</STRONG><STRONG>开发中常见几种非托管对象的释放</STRONG></P>
<P >我们知道.Net中对于内存的管理有两种方式,一种是托管对象管理,另一种是非托管对象管理。而我们通常理解的内存管理就是GC(垃圾收集),虽然GC通过对托管堆的管理,可以使我们有机会从繁锁的诸如内存泄漏之类的问题中解放出来,可以将精力专注于程序的逻辑上。但是将所有的事情都交给GC有时会损及程序的效率,严重的甚至会导致错误。</P>
<P >为什么会出现这种情况呢?问题在于对非托管资源(文件句柄)或者需要特别关照的对象(Bitmap)对象等,GC表现得就有点差强人意了(这句话或许说得并不正确,因为微软设计GC的本意就是用来针对托管对象管理)。如何有效地利用GC来进行内存管理,如何对程序的性能进行优化不是本文讨论的范围。本文的要旨在于AE开发中如何来释放非托管对象。</P>
<P ><STRONG>一、<A>AOUninitialize.Shutdown</A>.</STRONG></P>
<P >很多时候我们都会遇到这种情况:在退出AE应用程序中,常常提示这样的错误:“The instruction x references memory at x. The memory could not be read”。出现这种错误的原因主要在于COM对象(非托管对象)没有释放,在我们结束使用它的进程的时候,它阻止我们正常释放它,它释放的优先级高于当前使用它的进程释放的优先级,也就是说进程释放之前,必须先释放掉它。</P>
<P >明白了上面的原理,那么解决这一问题的方法便非常简单,我们只需在应用程序退出之前调用ESRI.ArcGIS.ADF.COMSupport.AOUninitialize.Shutdown()方法即可释放非托管对象了(9.2之前的版本AoUninitialize并不在ESRI.ArcGIS.ADF.COMSupport命名空间下,需注意)。</P>
<P ><STRONG>二、Marshal.ReleaseComObject</STRONG></P>
<P >NET开发中,引用COM对象主要是通过RCW(Runtime Callable Wrappers)机制来实现的(有点类似于代理模式)。对于COM对象的释放,GC表现得有点无能为力,因此必须在程序中显示释放掉COM对象占用的资源,否则将会出现一些意想不到的错误。比如重复地从Personal GeoDataBase中打开GeoDataBase Cursors而又没有及时释放,将会引发“No more tables can be opened.”其它情形中,你可能会发现应用程序退出时,COM对象依然在内存中引用。比如StyleGallery如果没有显示释放,在应用程序退出时就会引发错误。</P>
<P ><STRONG>1</STRONG><STRONG>、Releasing StyleGallery:</STRONG></P><PRE ><CODE>private void</CODE> MyFunction() </PRE><PRE >{</PRE><PRE > IStyleGallery styCls = <CODE>new</CODE> StyleGalleryClass() <CODE>as</CODE> IStyleGallery;</PRE><PRE > <CODE>// Use the StyleGalleryClass here ...</CODE></PRE><PRE > <CODE>int</CODE> refsLeft = 0;</PRE><PRE > <CODE>do</CODE></PRE><PRE > {</PRE><PRE >    refsLeft = Marshal.ReleaseComObject(styCls);</PRE><PRE > }</PRE><PRE > <CODE>while</CODE> (refsLeft > 0);</PRE><PRE >}</PRE>
<P ><STRONG>2</STRONG><STRONG>、Releasing geodatabase cursors</STRONG></P>
<P  align=left><CODE>for</CODE> (<CODE>int</CODE> i = 1; i < 2500; i++)</P><PRE > {</PRE><PRE >      IQueryFilter qu = New QueryFilterClass();</PRE><PRE >       qu.WhereClause = @"Area = " + i.ToString();</PRE><PRE >      IFeatureCursor featCursor = featClass.Search(qu, <CODE>true</CODE>);</PRE><PRE >      <CODE>// Use the feature cursor as required</CODE></PRE><PRE >      System.Runtime.InteropServices.Marshal.ReleaseComObject(featCursor);</PRE><PRE >  }</PRE>
<P ><STRONG>3</STRONG><STRONG>、</STRONG><STRONG>Releasing WebObject(ArcGIS Server)</STRONG></P><PRE ><CODE>private void</CODE> doSomthing_Click(<CODE>object</CODE> sender, System.EventArgs e)</PRE><PRE >{</PRE><PRE > <CODE>using</CODE> (WebObject webobj = <CODE>new</CODE> WebObject())</PRE><PRE > {</PRE><PRE >    ServerConnection serverConn = <CODE>new</CODE> ServerConnection("doug", <CODE>true</CODE>);</PRE><PRE >    IServerObjectManager som = serverConn.ServerObjectManager;</PRE><PRE >    IServerContext ctx = som.CreateServerContext("Yellowstone","MapServer");</PRE><PRE >    IMapServer mapsrv = ctx.ServerObject <CODE>as</CODE> IMapServer;</PRE><PRE >    IMapServerObjects mapo = mapsrv <CODE>as</CODE> IMapServerObjects;</PRE><PRE >    IMap map = mapo.get_Map(mapsrv.DefaultMapName);</PRE><PRE >    IFeatureLayer flayer = map.get_Layer(0) <CODE>as</CODE> IFeatureLayer;</PRE><PRE >    IFeatureClass fclass = flayer.FeatureClass;</PRE><PRE >    IFeatureCursor fcursor = fclass.Search(<CODE>null</CODE>, <CODE>true</CODE>);</PRE><PRE >    webobj.ManageLifetime(fcursor);</PRE><PRE >    IFeature f = null;</PRE><PRE >    <CODE>while</CODE> ((f = fcursor.NextFeature()) != <CODE>null</CODE>)</PRE><PRE >    {</PRE><PRE >      <CODE>// do something with the feature</CODE></PRE><PRE >    }</PRE><PRE >    ctx.ReleaseContext();</PRE><PRE > }</PRE><PRE >}</PRE>
<P ><STRONG>三、什么时候应该释放非托管对象?</STRONG></P>
<P >这个问题非常重要,当我们确信在释放之后不再调用非托管对象资源时候,就可以调用System.Runtime.InteropServices.Marshal.ReleaseComObject()方法进行显式释放了,否则将会引发新的错误。</P>
<P >总结:本文简单的列举了AE开发中几种常见非托管对象的释放问题,以供大家参考。有些方面说得不够详细,大家可以从ArcGIS Engine帮助中求得详细资料。</P>
喜欢0 评分0
A friend is never known till a man has need. ...CL
zyxgis
路人甲
路人甲
  • 注册日期2004-09-01
  • 发帖数28
  • QQ
  • 铜币122枚
  • 威望0点
  • 贡献值0点
  • 银元0个
1楼#
发布于:2008-07-21 20:46
<P>这个好像是AE帮助中的,我个人建议不要使用ReleaseComObject,而使用FinalReleaseComObject</P>
举报 回复(0) 喜欢(0)     评分
hover
路人甲
路人甲
  • 注册日期2005-12-13
  • 发帖数69
  • QQ
  • 铜币279枚
  • 威望0点
  • 贡献值0点
  • 银元0个
2楼#
发布于:2008-07-24 09:39
<P>开发过程中,对代码的结构控制好的话,我个人建议用ReleaseComObject。因为ReleaseComObject只是把现在正在用的COM引用去掉。如果用FinalReleaseComObject是直接把COM清掉,对一些代码可能会产生影响。</P>
承接、合作各种GIS项目开发 :ArcGIS平(基于AO、AE、ArcIMS、ArcServer开发) :MapInfo平台(基于MapXtreme 2004/2005、MapXtreme For Java开发) E-Mail:cmcrj0929@163.com QQ:31814576 有国土、市政、交通、电力等行业的成功应用项目经验。
举报 回复(0) 喜欢(0)     评分
游客

返回顶部