应用程序域和程序集

本主题描述应用程序域和程序集之间的关系。 在可以执行程序集中所包含的代码之前,必须将程序集加载到应用程序域中。 运行普通的应用程序会导致将几个程序集加载到一个应用程序域中。

程序集的加载方式决定其实时 (JIT) 编译代码是否可以在进程中由多个应用程序域共享,以及该程序集是否可以从进程中卸载。

  • 如果程序集是以非特定于域的形式进行加载,则共享相同安全授权集的所有应用程序域都可以共享相同的 JIT 编译代码,从而减少应用程序所需的内存。 但是,程序集则永远不能从进程中卸载。

  • 如果程序集不是以非特定于域的形式进行加载,则它必须在加载的每个应用程序域中都是 JIT 编译的。 但是,通过卸载程序集加载的所有应用程序域,可以从进程中卸载程序集。

运行时宿主决定在将运行时加载到进程中时是否以非特定于域的形式加载程序集。 对于托管应用程序,将 LoaderOptimizationAttribute 特性应用于进程的入口点方法,并从关联的 LoaderOptimization 枚举指定一个值。 对于承载公共语言运行时的非托管应用程序,当您调用 CorBindToRuntimeEx 函数 方法时,指定适当的标志。

有三个选项用于加载非特定于域的程序集:

  • SingleDomain 不以非特定于域的形式加载任何程序集(Mscorlib 除外,它始终以非特定于域的形式加载)。 此设置称作单域,因为它通常用在宿主只运行进程中的单个应用程序时。

  • MultiDomain 以非特定于域的形式加载所有程序集。 此设置用于以下情况:进程中有多个应用程序域,所有这些应用程序域均运行相同的代码。

  • MultiDomainHost 以非特定于域的形式加载强名称程序集(如果它们以及它们的所有依赖项都已在全局程序集缓存中安装)。 其他程序集都将针对它们加载的每个应用程序域分别进行加载和 JIT 编译,从而可以从进程中卸载。 如果您在同一进程中运行多个应用程序,或者如果您有混合的程序集,其中包括许多应用程序域共享的程序集和需要从进程中卸载的程序集,则可以使用此设置。

以下程序集不能共享 JIT 编译代码:使用 Assembly 类的 LoadFrom 方法加载到“加载源”上下文中的程序集,或者使用 Load 方法的重载(指定字节数组)从图像加载的程序集。

使用 Ngen.exe(本机映像生成器) 编译为本机代码的程序集如果在第一次加载到进程中时是以非特定于域的形式加载的,则可以在不同应用程序域之间共享这些程序集。

包含应用程序入口点的程序集的 JIT 编译代码只有在其所有依赖项都可以被共享的情况下,才可以被共享。

非特定于域的程序集可以进行多次 JIT 编译。 例如,如果两个应用程序域的安全授权集不同,则它们不能共享相同的 JIT 编译代码。 但是,JIT 编译程序集的每个副本都可以与其他具有相同授权集的应用程序域共享。

当您决定是否以非特定于域的形式加载程序集时,必须在减少内存占用和降低其他性能因素之间加以权衡。

  • 对于非特定于域的程序集,对静态数据和方法的访问较慢的原因在于需要隔离程序集。 访问该程序集的每一应用程序域都必须具有静态数据的单独副本,以避免跨域边界引用静态字段中的对象。 因此,运行时包含附加的逻辑,用以将调用方引导到静态数据或静态方法的适当副本。 这一额外的逻辑将降低调用速度。

  • 当以非特定于域的形式加载程序集时,必须找到并加载该程序集的所有依赖项,因为如果一个依赖项不能以非特定于域的形式加载,则会妨碍以非特定于域的形式加载程序集。

请参见

概念

应用程序域

公共语言运行时中的程序集