zoukankan      html  css  js  c++  java
  • 【转】.NET+AE开发中常见几种非托管对象的释放

    尝试读取或写入受保护的内存。这通常指示其他内存已损坏。

     今天在开发时遇到一个问题:" 未处理 System.AccessViolationException Message="尝试读取或写入受保护的内存。这通常指示其他内存已损坏。"      

    这通常指示其他内存已损坏。不知大家遇到过没有,这种错误是由于用户反复写入或打开文件,

          最终使得内存资源没有及时释放导致此错误。这种错误是无法跟踪的,必须强制释放!

          没有强制的释放方法,底层的com组件根据你进程调用组件的次数来控制对象的增加和释放(对象释放会延迟,

          com自   身的问题)。一般是调用强制垃圾回收或ao自带的回收对象的方法,效果不明显。解决方法如下:

             1.将IIS重新启动。(我是按此方法解决的。)

             2.关闭VS进程,退出VS2005.

             3.上述方法若不行的话,可以自己在程序里强制释放COM资源,调用Marshal.ReleaseComObject()方法将不再使用的对象释放掉。

     

     

     

     

    NET+AE开发中常见几种非托管对象的释放
    .NET+AE开发中常见几种非托管对象的释放
    我们知道.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:
    private void MyFunction()
    {
    IStyleGallery styCls = new StyleGalleryClass() as IStyleGallery;
    // Use the StyleGalleryClass here ...
    int refsLeft = 0;
    do
    {
        refsLeft = Marshal.ReleaseComObject(styCls);
    }
    while (refsLeft > 0);
    }
    2、Releasing geodatabase cursors
    for (int i = 1; i < 2500; i++)
    {
          IQueryFilter qu = New QueryFilterClass();
           qu.WhereClause = @"Area = " + i.ToString();
          IFeatureCursor featCursor = featClass.Search(qu, true);
          // Use the feature cursor as required
          System.Runtime.InteropServices.Marshal.ReleaseComObject(featCursor);
    }
    3、Releasing WebObject(ArcGIS Server)
    private void doSomthing_Click(object sender, System.EventArgs e)
    {
    using (WebObject webobj = new WebObject())
    {
        ServerConnection serverConn = new ServerConnection("doug", true);
        IServerObjectManager som = serverConn.ServerObjectManager;
        IServerContext ctx = som.CreateServerContext("Yellowstone","MapServer");
        IMapServer mapsrv = ctx.ServerObject as IMapServer;
        IMapServerObjects mapo = mapsrv as IMapServerObjects;
        IMap map = mapo.get_Map(mapsrv.DefaultMapName);
        IFeatureLayer flayer = map.get_Layer(0) as IFeatureLayer;
        IFeatureClass fclass = flayer.FeatureClass;
        IFeatureCursor fcursor = fclass.Search(null, true);
        webobj.ManageLifetime(fcursor);
        IFeature f = null;
        while ((f = fcursor.NextFeature()) != null)
        {
          // do something with the feature
        }
        ctx.ReleaseContext();
    }
    }
    三、什么时候应该释放非托管对象?
    这个问题非常重要,当我们确信在释放之后不再调用非托管对象资源时候,就可以调用System.Runtime.InteropServices.Marshal.ReleaseComObject()方法进行显式释放了,否则将会引发新的错误。
    总结:本文简单的列举了AE开发中几种常见非托管对象的释放问题,以供大家参考。有些方面说得不够详细,大家可以从ArcGIS Engine帮助中求得详细资料。

  • 相关阅读:
    详解ASP.NET的内置对象
    如何架设FTP服务器
    输出JSON问题
    new , virtual , override
    Javascript 操作select控件大全(新增、修改、删除、选中、清空、判断存在等)
    Java回顾之I/O
    数据结构之栈和队列
    Java回顾之多线程同步
    设计模式之行为型模式
    Java回顾之网络通信
  • 原文地址:https://www.cnblogs.com/summer_adai/p/3412514.html
Copyright © 2011-2022 走看看