互操作封送处理

互操作封送处理控制调用期间,通过方法参数和返回值在托管内存和非托管内存之间传递数据的方式。 互操作封送处理是由公共语言运行时的封送处理服务执行的运行时活动。

大多数数据类型在托管和非托管内存中都具有公共的表示形式。 Interop 封送拆收器为您处理这些类型。 其他类型可能是不明确的,或根本不在托管内存中表示。

不明确的类型可能或者具有多种映射到单个托管类型的非托管表示形式,或者缺少类型信息(如数组的大小)。 对于不明确的类型,封送拆收器提供默认表示形式和替换表示形式(存在多种表示形式)。 可以向封送拆收器提供有关它如何封送不明确类型的显式指令。

本概述包含以下几节:

  • 平台调用和 COM 互操作模型

  • 封送处理和 COM 单元

  • 封送远程调用

  • 相关主题

  • 参考

平台调用和 COM 互操作模型

公共语言运行时提供两种用于与非托管代码进行交互的机制:

  • 平台调用,它使托管代码能够调用从非托管库中导出的函数。

  • COM 互操作,它使托管代码能够通过接口与组件对象模型 (COM) 对象交互。

平台调用和 COM 互操作都使用互操作封送处理在调用方和被调用方之间准确地移动方法参数,并且如果需要,也可以将数据从被调用方移回调用方。 正如下面的插图所示,除涉及回调函数时以外,平台调用方法调用从托管代码流向非托管代码,而绝不会以相反方向流动。 虽然平台调用的调用只能从托管代码流向非托管代码,但是数据仍然可以作为输入参数或输出参数在两个方向流动。 COM 互操作方法调用可以在任一个方向流动。

平台调用和 COM 互操作调用流

平台调用

在最低级别,这两种机制都使用同一种互操作封送处理服务;不过,某些数据类型则仅受 COM 互操作或平台调用支持。 有关详细信息,请参见默认封送处理行为

返回页首

封送处理和 COM 单元

Interop 封送拆收器在公共语言运行时堆和非托管堆之间封送数据。 每当调用方和被调用方无法操作数据的同一个实例时就发生封送处理。 Interop 封送拆收器使调用方和被调用方都能够看上去像是在操作同一数据,即使它们都有自己的数据副本。

COM 也有一个在 COM 单元或不同的 COM 进程之间封送数据的封送拆收器。 当在同一个 COM 单元内的托管和非托管代码之间进行调用时,Interop 封送拆收器是涉及到的唯一一个封送拆收器。 当在另一个 COM 单元或另一个进程中的托管代码和非托管代码之间进行调用时,则同时涉及 Interop 封送拆收器和 COM 封送拆收器。

COM 客户端和托管服务器

具有由Regasm.exe(程序集注册工具) 注册的类型库的导出的托管服务器有一个设置为 Both 的 ThreadingModel 注册表项。 该值指示服务器可以在单线程单元 (STA) 或多线程单元 (MTA) 中激活。 服务器对象在与其调用方相同的单元中创建,如下表所示。

COM 客户端

.NET 服务器

封送处理要求

STA

Both 将变成 STA。

相同单元封送处理。

MTA

Both 将变成 MTA。

相同单元封送处理。

由于客户端和服务器位于同一单元中,因此互操作封送处理服务将自动处理所有数据封送处理。 下面的插图显示了在同一个 COM 样式的单元内的托管和非托管堆之间进行的互操作封送处理服务。

相同单元封送处理进程

互操作封送处理

如果计划导出托管服务器,请注意,COM 客户端确定服务器的单元。 在 MTA 中初始化的 COM 客户端所调用的托管服务器必须确保线程安全。

托管客户端和 COM 服务器

托管客户端单元的默认设置为 MTA;但是,.NET 客户端的应用程序类型可以更改默认设置。 例如,Visual Basic 2005 客户端单元设置为 STA。 您可以使用 System.STAThreadAttributeSystem.MTAThreadAttributeThread.ApartmentState 属性或 Page.AspCompatMode 属性检查并更改托管客户端的单元设置。

组件的作者设置 COM 服务器的线程关联。 下表显示 .NET 客户端和 COM 服务器的单元设置的组合。 同时还显示得到的针对这些组合的封送处理要求。

.NET 客户端

COM 服务器

封送处理要求

MTA(默认)

MTA

STA

互操作封送处理。

Interop 和 COM 封送处理。

STA

MTA

STA

Interop 和 COM 封送处理。

互操作封送处理。

当托管客户端和非托管服务器位于同一单元中时,互操作封送处理服务处理所有数据封送处理。 不过,当客户端和服务器在不同的单元中初始化时,还需要 COM 封送处理。 下面的插图显示跨单元调用的元素。

.NET 客户端和 COM 对象之间的跨单元调用

COM 封送处理

对于跨单元封送处理,可以执行下列操作:

  • 接受跨单元封送处理的系统开销,它只在存在许多跨边界调用时才值得注意。 若要使调用能够成功跨过单元边界,必须注册 COM 组件的类型库。

  • 通过将客户端线程设置为 STA 或 MTA 改变主线程。 例如,如果 C# 客户端调用许多 STA COM 组件,则可以通过将主线程设置为 STA 来避免跨单元封送处理。

    注意注意

    将 C# 客户端的线程设置为 STA 后,对 MTA COM 组件的调用将需要跨单元封送处理。

有关显式选择单元模型的说明,请参见托管和非托管线程处理

返回页首

封送远程调用

与跨单元封送处理一样,只要对象驻留在不同的进程中,托管代码和非托管代码之间的每个调用就都涉及 COM 封送处理。 例如:

  • 调用远程主机上的托管服务器的 COM 客户端使用分布式 COM (DCOM)。

  • 调用远程主机上的 COM 服务器的托管客户端使用 DCOM。

下面的插图显示互操作封送处理和 COM 封送处理如何跨越进程和主机边界提供通信信道。

跨进程封送处理

COM 封送处理

保留标识

公共语言运行时保留托管和非托管引用的标识。 下面的插图显示跨越进程和主机边界的直接非托管引用(顶部的行)和直接托管引用(底部的行)的流。

跨越进程和主机边界传递的引用

COM 可调用包装和运行时可调用包装

本插图中:

  • 非托管客户端从一个托管对象获取一个对 COM 对象的引用,而该托管对象是从一台远程主机获取该引用的。 远程处理机制为 DCOM。

  • 托管客户端从一个 COM 对象获取一个对托管对象的引用,而该 COM 对象是从一台远程主机获取该引用的。 远程处理机制为 DCOM。

    注意注意

    必须注册该托管服务器的导出类型库。

调用方和被调用方之间的进程边界的数目并不相干;对于进程内和进程外调用都会发生相同的直接引用处理。

托管远程处理

运行时还提供了托管远程处理,可用于跨进程和主机边界建立托管对象之间的通信信道。 托管远程处理可以适应通信组件之间的防火墙,如下面的插图所示。

跨越使用 SOAP 或 TcpChannel 类的防火墙的远程调用

SOAP 或 TcpChannel

某些非托管调用可以通过 SOAP 传递,如服务组件和 COM 之间的调用。 有关使用托管远程处理的其他信息,请参见 .NET Remoting Overview

返回页首

相关主题

标题

说明

默认封送处理行为

介绍互操作封送处理服务用来封送数据的规则。

用平台调用封送数据

介绍如何声明方法形参以及如果将实参传递给由非托管库导出的函数。

用 COM 互操作对数据进行封送处理

描述如何自定义 COM 包装以改变封送处理行为。

如何:映射 HRESULT 和异常

介绍如何将自定义异常映射到 HRESULT,并提供从每个 HRESULT 到其在 .NET Framework 中的相似异常类的完整映射。

使用泛型类型进行交互操作

描述在使用用于 COM 互操作性的泛型类型时,哪些操作受支持。

与非托管代码交互操作

描述公共语言运行时所提供的互操作性服务。

高级 COM 互操作性

提供一些链接,指向关于将 COM 组件并入 .NET Framework 应用程序中的更多信息。

互操作的设计注意事项

提供有关编写集成 COM 组件的提示。

.NET Remoting

介绍 .NET Framework 中为远程通信提供的多种方法。

返回页首

参考

System.Runtime.InteropServices

返回页首