• 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
  • 相关阅读:
    Data Lake_理解数据湖
    spire.Doc -Index was out of the range
    R6_ES在互联网公司应用案例汇总参考
    R5_ES读写流程
    R4_Elasticsearch Mapping parameters
    华强北二代悦虎1562M升级固件图文教程(详细多图文)
    MMI_UT洛达检测1562A软件使用,Airoha_SDK_UT使用(多图)
    悦虎144固件,151固件,华强北二代悦虎144固件,151固件,1562M芯片144固件,151固件
    CentOS7安装redis并配置外网可访问(局域网可参考)
    CentOS离线安装gcc环境(附安装包+图文并茂)
  • 原文地址:https://www.cnblogs.com/atravellers/p/1653812.html
Copyright © 2020-2023  润新知