zoukankan      html  css  js  c++  java
  • C# 使用SuperMap控件需要千万注意的地方(转载)

     C# 使用SuperMap控件需要千万注意的地方

    讨论SuperMap前,我们衷心的希望微软能够改进垃圾回收器,更加智能的帮助开发人员释放对象。
    首先看下传统的COM对象与.NET框架对象模型的创建与释放的不同:
    (1)、COM对象的客户必须自己管理COM对象的生存期,而.NET对象的生存期由CLR(Common Language Runtime)来管理,即通过GC(Garbage Collection)机制自动回收。
    (2)、COM对象的客户通过指针引用COM对象,对象在内存中的位置是不变的,而.NET对象在内存中的驻留由.NET框架执行环境(execution environment)来管理,对象在内存中的位置是可变的,比如出于优化性能的考虑,同时会更新所有对对象的引用。这一点也是以CLR中不使用指针为前提的。
    简单的说.com客户每次引用对象的时候,就调用
              IUnKnown->AddRef(),而每次释放对象的时候,就调用
              IUnKnown->Release(),一旦引用计数达到零,就释放实例。
    如何在.NET中Release彻底释放呢?非常幸运,在.net中允许程序员显式地自己调用com的Release方法,这个方法叫做System.Runtime.InteropServices.Marshal.ReleaseComObject。

    现在来说SuperMap,根本上讲SuperMap的控件在.NET中都是COM对象,这次我们讨论的要点就是如何写才能完全彻底的释放COM对象。先来看段代码:
    private void axSuperMap1_Tracked(object sender, EventArgs e)
    {
    soDatasetVector _soDatasetVector = SuperWorkspace.Datasources[0].Datasets[0] as soDatasetVector;
    soRecordset _soRecordset = _soDatasetVector.Query("1=2", true, null, "");
    if (_soRecordset.AddNew(axSuperMap1.TrackedGeometry, null) == -1)
    {
           MessageBox.Show("添加数据失败");
    }
    System.Runtime.InteropServices.Marshal.ReleaseComObject(_soRecordset);
    _soRecordset = null;
    System.Runtime.InteropServices.Marshal.ReleaseComObject(_soDatasetVector);
    _soDatasetVector = null;
    }
    这段代码看似相当的简洁 风格很棒。但是实际上却没有释放完全。
    现在我们就来说标题上的“千万千万”的地方。
    对于一些隐含返回的对象,也要这样调用ReleaseComObject才能将其正确释放,并保证其正常运作。
    对于一些隐含返回的对象,也要这样调用ReleaseComObject才能将其正确释放,并保证其正常运作。
    对于一些隐含返回的对象,也要这样调用ReleaseComObject才能将其正确释放,并保证其正常运作。

    现在我们来看看上面这段代码的释放完全的写法:
    private void axSuperMap1_Tracked(object sender, EventArgs e)
    {
    soDataSources _soDataSources = SuperWorkspace.Datasources;
    soDataSource _soDataSource = SuperWorkspace.Datasources[0];
    soDatasets _soDatasets=_soDataSource.Datasets;
    soDataset _Dataset = _soDatasets[0];
    soDatasetVector _soDatasetVector = _Dataset as soDatasetVector;
    soGeometry _soGeometry = axSuperMap1.TrackedGeometry;
    soRecordset _soRecordset = _soDatasetVector.Query("1=2", true, null, "");
    if (_soRecordset.AddNew(_soGeometry, null) == -1)
    {
           MessageBox.Show("添加数据失败");
    }
    System.Runtime.InteropServices.Marshal.ReleaseComObject(_soGeometry);
    _soGeometry = null;
    System.Runtime.InteropServices.Marshal.ReleaseComObject(_soRecordset);
    _soRecordset = null;
    System.Runtime.InteropServices.Marshal.ReleaseComObject(_soDatasetVector);
    _soDatasetVector = null;
    System.Runtime.InteropServices.Marshal.ReleaseComObject(_Dataset);
    _Dataset = null;
    System.Runtime.InteropServices.Marshal.ReleaseComObject(_soDatasets);
    _soDatasets = null;
    System.Runtime.InteropServices.Marshal.ReleaseComObject(_soDataSource);
    _soDataSource = null;
    System.Runtime.InteropServices.Marshal.ReleaseComObject(_soDataSources);
    _soDataSources = null;
    }

    你没看错,其实我也很郁闷。这样写的确很弱,很委琐。
    但是千万记住,如果不想你写的产品在你想不到的时候弹出“System.AccessViolationException: 尝试读取或写入受保护的内存。这通常指示其他内存已损坏。”的错误,还是老实再老实的用这很弱的写法吧。
    转载自http://www.gisbox.cn/thread-156-1-1.html
  • 相关阅读:
    resolv.conf 是什么
    Cloudera Manager Free Edition 4.1 和CDH 4.1.2 简易安装教学
    bach cello
    windows 7 旗舰版 切换 中英文 界面
    geghi 教程 以lesmiserable 为例
    python 使用 tweepy 案例: PS4
    用Live Writer写博文插入程序代码的三个插件比较
    侧滑菜单
    [Android]简略的Android消息机制源码分析
    常用git命令
  • 原文地址:https://www.cnblogs.com/atravellers/p/1653812.html
Copyright © 2011-2022 走看看