博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
【20101110-01】NET+AE开发中常见几种非托管对象的释放【转帖】.
阅读量:5246 次
发布时间:2019-06-14

本文共 2650 字,大约阅读时间需要 8 分钟。

我们知道.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:

  1. private void MyFunction()
  2. {
  3. IStyleGallery styCls = new StyleGalleryClass() as IStyleGallery;
  4. // Use the StyleGalleryClass here ...
  5. int refsLeft = 0;
  6. do
  7. {
  8.     refsLeft = Marshal.ReleaseComObject(styCls);
  9. }
  10. while (refsLeft > 0);
  11. }
复制代码

2、Releasing geodatabase cursors

  1. for (int i = 1; i < 2500; i++)
  2. {
  3.       IQueryFilter qu = New QueryFilterClass();
  4.        qu.WhereClause = @"Area = " + i.ToString();
  5.       IFeatureCursor featCursor = featClass.Search(qu, true);
  6.       // Use the feature cursor as required
  7.       System.Runtime.InteropServices.Marshal.ReleaseComObject(featCursor);
  8.   }
复制代码

3、Releasing WebObject(ArcGIS Server)

  1. private void doSomthing_Click(object sender, System.EventArgs e)
  2. {
  3. using (WebObject webobj = new WebObject())
  4. {
  5.     ServerConnection serverConn = new ServerConnection("doug", true);
  6.     IServerObjectManager som = serverConn.ServerObjectManager;
  7.     IServerContext ctx = som.CreateServerContext("Yellowstone","MapServer");
  8.     IMapServer mapsrv = ctx.ServerObject as IMapServer;
  9.     IMapServerObjects mapo = mapsrv as IMapServerObjects;
  10.     IMap map = mapo.get_Map(mapsrv.DefaultMapName);
  11.     IFeatureLayer flayer = map.get_Layer(0) as IFeatureLayer;
  12.     IFeatureClass fclass = flayer.FeatureClass;
  13.     IFeatureCursor fcursor = fclass.Search(null, true);
  14.     webobj.ManageLifetime(fcursor);
  15.     IFeature f = null;
  16.     while ((f = fcursor.NextFeature()) != null)
  17.     {
  18.       // do something with the feature
  19.     }
  20.     ctx.ReleaseContext();
  21. }
  22. }
复制代码

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

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

转载于:https://www.cnblogs.com/willwayer/archive/2010/11/10/1874017.html

你可能感兴趣的文章
WPF自定义集合控件概述与遇到的问题
查看>>
路由器外接硬盘做nas可行吗?
查看>>
python:从迭代器,到生成器,再到协程的示例代码
查看>>
pytest的参数化测试
查看>>
Java多线程系列——原子类的实现(CAS算法)
查看>>
安装Pygame和pip的艰辛之路
查看>>
Hibernate的实体类为什么需要实现 java.io.Serializable 接口
查看>>
在Ubuntu下配置Apache多域名服务器
查看>>
多线程《三》进程与线程的区别
查看>>
Min Stack
查看>>
老鸟的Python入门教程
查看>>
Ubuntu下非常给力的下载工具--uget+aria2
查看>>
Nginx配置
查看>>
棋盘覆盖问题
查看>>
vs2003无法调试 解决方法收藏
查看>>
.net-一般处理程序及生命周期
查看>>
linux sed命令
查看>>
[Cycle.js] Making our toy DOM Driver more flexible
查看>>
LeetCode 160. Intersection of Two Linked Lists
查看>>
html标签的嵌套规则
查看>>