注册 登录  
 加关注
   显示下一条  |  关闭
温馨提示!由于新浪微博认证机制调整,您的新浪微博帐号绑定已过期,请重新绑定!立即重新绑定新浪微博》  |  关闭

naigeer的知识库

不断学习,用知识武装头脑,用头脑创造未来!

 
 
 

日志

 
 

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

2008-09-24 19:15:15|  分类: ArcGIS开发 |  标签: |举报 |字号 订阅

  下载LOFTER 我的照片书  |

我们知道.Net中对于内存的管理有两种方式,一种是托管对象管理,另一种是非托管对象管理。而我们通常理解的内存管理就是GC(垃圾收集),虽然GC通过对托管堆的管理,可以使我们有机会从繁锁的诸如内存泄漏之类的问题中解放出来,可以将精力专注于程序的逻辑上。但是将所有的事情都交给GC有时会损及程序的效率,严重的甚至会导致错误。

为什么会出现这种情况呢?问题在于对非托管资源(文件句柄)或者需要特别关照的对象(Bitmap)对象等,GC表现得就有点差强人意了(这句话或许说得并不正确,因为微软设计GC的本意就是用来针对托管对象管理)。如何有效地利用GC来进行内存管理,如何对程序的性能进行优化不是本文讨论的范围。本文的要旨在于AE开发中如何来释放非托管对象。

一、AOUninitialize.Shutdown.

很多时候我们都会遇到这种情况:在退出AE应用程序中,常常提示这样的错误:“The instruction x references memory at x. The memory could not be read”。出现这种错误的原因主要在于COM对象(非托管对象)没有释放,在我们结束使用它的进程的时候,它阻止我们正常释放它,它释放的优先级高于当前使用它的进程释放的优先级,也就是说进程释放之前,必须先释放掉它。

明白了上面的原理,那么解决这一问题的方法便非常简单,我们只需在应用程序退出之前调用ESRI.ArcGIS.ADF.COMSupport.AOUninitialize.Shutdown()方法即可释放非托管对象了(9.2之前的版本AoUninitialize并不在ESRI.ArcGIS.ADF.COMSupport命名空间下,需注意)。

二、Marshal.ReleaseComObject

NET开发中,引用COM对象主要是通过RCW(Runtime Callable Wrappers)机制来实现的(有点类似于代理模式)。对于COM对象的释放,GC表现得有点无能为力,因此必须在程序中显示释放掉COM对象占用的资源,否则将会出现一些意想不到的错误。比如重复地从Personal GeoDataBase中打开GeoDataBase Cursors而又没有及时释放,将会引发“No more tables can be opened.”其它情形中,你可能会发现应用程序退出时,COM对象依然在内存中引用。比如StyleGallery如果没有显示释放,在应用程序退出时就会引发错误。

1、Releasing StyleGallery:

DE<private voidDE< MyFunction() 
{
 IStyleGallery styCls = DE<newDE< StyleGalleryClass() DE<asDE< IStyleGallery;
 DE<// Use the StyleGalleryClass here ...DE<
 DE<intDE< refsLeft = 0;
 DE<doDE<
 {
    refsLeft = Marshal.ReleaseComObject(styCls);
 }
 DE<whileDE< (refsLeft > 0);
}

2、Releasing geodatabase cursors

DE<forDE< (DE<intDE< i = 1; i < 2500; i++)

 {
      IQueryFilter qu = New QueryFilterClass();
       qu.WhereClause = @"Area = " + i.ToString();
      IFeatureCursor featCursor = featClass.Search(qu, DE<trueDE<);
      DE<// Use the feature cursor as requiredDE<
      System.Runtime.InteropServices.Marshal.ReleaseComObject(featCursor);
  }

3Releasing WebObject(ArcGIS Server)

DE<private voidDE< doSomthing_Click(DE<objectDE< sender, System.EventArgs e)
{
 DE<usingDE< (WebObject webobj = DE<newDE< WebObject())
 {
    ServerConnection serverConn = DE<newDE< ServerConnection("doug", DE<trueDE<);
    IServerObjectManager som = serverConn.ServerObjectManager;
    IServerContext ctx = som.CreateServerContext("Yellowstone","MapServer");
    IMapServer mapsrv = ctx.ServerObject DE<asDE< IMapServer;
    IMapServerObjects mapo = mapsrv DE<asDE< IMapServerObjects;
    IMap map = mapo.get_Map(mapsrv.DefaultMapName);
    IFeatureLayer flayer = map.get_Layer(0) DE<asDE< IFeatureLayer;
    IFeatureClass fclass = flayer.FeatureClass;
    IFeatureCursor fcursor = fclass.Search(DE<nullDE<, DE<trueDE<);
    webobj.ManageLifetime(fcursor);
    IFeature f = null;
    DE<whileDE< ((f = fcursor.NextFeature()) != DE<nullDE<)
    {
      DE<// do something with the featureDE<
    }
    ctx.ReleaseContext();
 }
}

三、什么时候应该释放非托管对象?

这个问题非常重要,当我们确信在释放之后不再调用非托管对象资源时候,就可以调用System.Runtime.InteropServices.Marshal.ReleaseComObject()方法进行显式释放了,否则将会引发新的错误。

总结:本文简单的列举了AE开发中几种常见非托管对象的释放问题,以供大家参考。有些方面说得不够详细,大家可以从ArcGIS Engine帮助中求得详细资料。

参考资料:

1、 谈谈.NET中的内存管理 

2、 ArcGIS Engine开发帮助

  评论这张
 
阅读(466)| 评论(0)
推荐 转载

历史上的今天

评论

<#--最新日志,群博日志--> <#--推荐日志--> <#--引用记录--> <#--博主推荐--> <#--随机阅读--> <#--首页推荐--> <#--历史上的今天--> <#--被推荐日志--> <#--上一篇,下一篇--> <#-- 热度 --> <#-- 网易新闻广告 --> <#--右边模块结构--> <#--评论模块结构--> <#--引用模块结构--> <#--博主发起的投票-->
 
 
 
 
 
 
 
 
 
 
 
 
 
 

页脚

网易公司版权所有 ©1997-2017