zoukankan      html  css  js  c++  java
  • .Net环境下COM互操作

    原创文章,转载请注明出处!

    接上文:http://www.cnblogs.com/yhlx125/archive/2011/11/22/2258543.html

    博文的最后产生了问题:GC.Collect()显著的释放了内存,难道强制GC清理的效果这么明显?产生的内存增长不是因为COM对象、Mxd文件,而是托管的内存?

    于是产生了这样的想法:MapClass、MapDocumentClass对象都是.Net托管对象,而非COM对象。事实是否如此呢?

    IMapDocument pMapDoc = new MapDocumentClass();

    int n = Marshal.ReleaseComObject(pMapDoc);

    确实是执行了,返回值为0,说明正确释放了COM对象。如果执行下一段代码则第2句报错,说明.Net对象不能用Marshal.ReleaseComObject()方法来操作。

    1    A pa = new A();
    2 int m = Marshal.ReleaseComObject(pa);
    3 MessageBox.Show(m.ToString());
    View Code
    class A
    {
    int a;

    public int A1
    {
    get { return a; }
    set { a = value; }
    }

    }

    于是查找相关资料:学习了如下主题:

    1. COM互操作性

    2. Primary Interop Assemblies (PIAs,主互操作程序集),http://msdn.microsoft.com/zh-cn/library/aax7sdch.aspx

    主互操作程序集是一个由供应商提供的唯一的程序集。它包含用 COM 实现的类型的类型定义(作为元数据)。 只能有一个主互操作程序集,而且该程序集必须由 COM 类型库的发行者用强名称签名。 一个主互操作程序集可以包装同一类型库的多个版本。

    如果导入为程序集的 COM 类型库不是由原类型库的发行者签名的,该类型库不能作为主互操作程序集。 只有类型库的发行者才能产生真正的主互操作程序集。该程序集将成为用于与基础 COM 类型进行互操作的正式类型定义单元。

    COM 组件的发行者生成主互操作程序集并将它们发布给开发人员以便在 .NET Framework 应用程序中使用。 对于发行者,本节提供有关产生主互操作程序集的信息。 对于开发人员,本节描述如何用主互操作程序集编程。

    3. COM包装:http://msdn.microsoft.com/zh-cn/library/5dxz80y2.aspx

    COM 包装(COM Wrapper)

    运行时提供了包装类,使托管和非托管客户端认为它们是在其各自的环境中调用对象。 每当托管客户端对某个 COM 对象调用方法时,运行时就会创建一个运行时可调用包装 (RCW)。 RCW 的功能之一是抽取托管和非托管引用机制之间的差异。 运行时还会创建一个 COM 可调用包装 (CCW) 来逆转此过程,使 COM 客户端能够对 .NET 对象无缝地调用方法。 如下图所示,调用代码的性质将确定运行时所创建的包装类。

    使用RCW,.NET客户程序就可以使用. Net对象而不是COM组件,所以不需要处理COM特性,这是由包装器来处理的。RCW隐藏了IUnknown接口和IDispatch接口并处理COM对象的引用数。(C#高级编程第六版 686页)

    于是问题明了了,IMap pMap = new MapClass();这句代码使用的MapClass是Esri公司提供的PIAs表现形式,PIAs包含用 COM 实现的类型的类型定义(作为元数据)。 MapClass对象本身是.Net对象,实现了对COM对象Map的包装,即可认为传递了Map对象的引用。所以上文末尾产生的问题,调用GC.Collect()显著的释放了内存是因为释放了MapClass这个包装对象,而包装RCW对象是COM到.Net的桥梁,(数据封送处理是否可以视为产生了数据的副本?)Marshal.ReleaseComObject(pMapDoc);释放了COM对象但是没有释放托管的RCW,所以内存要等托管运行时释放。

    (运行时所生成的标准 RCW 或 CCW 将为跨越 COM 和 .NET Framework 之间边界的调用提供充分的封送处理。)

    ReleaseComObject 方法递减运行库可调用包装的引用计数。当引用计数达到零时,运行库将释放非托管 COM 对象上的所有引用(COM本身是自计数的)。

    4.封送处理http://msdn.microsoft.com/zh-cn/library/9f9f3yxf.aspx

    文章未经说明均属原创,学习笔记可能有大段的引用,一般会注明参考文献。 欢迎大家留言交流,转载请注明出处。
  • 相关阅读:
    为什么要对url进行encode
    活在当下
    Linux Shell 文本处理工具
    Servlet、Servlet容器等内容讲解
    Java编程中的一些常见问题汇总
    创建文件目录
    ubuntu
    iptables
    mysqldump导入导出
    pt-table-sync
  • 原文地址:https://www.cnblogs.com/yhlx125/p/2286108.html
Copyright © 2011-2022 走看看