我们都知道,进程是操作系统进行资源调度和分配的基本单位,每个进程实际代表了当前应用程序从启动到结束的全部过程。对于Windows中的每一个.exe文件,在运行时都要由一个进程来承载它。与非托管.exe文件不同的是,托管.exe文件并没有直接将程序集加载到当前进程当中,而是将程序集加载到应用程序域中,然后将应用程序域加载到进程中。每个进程可以承载多个应用程序域。因此,对于托管程序,每个进程可以承载多个应用程序,这同时也提升了应用程序的性能,因为进程的切换所耗费的性能要多于应用程序域的切换。
1.1 应用程序域的特点
托管程序为什么要使用应用程序域呢?概括其优点如下:
1. 在一个应用程序中出现的错误不会影响其他应用程序。
2. 因为类型安全的代码不会导致内存错误,所以使用应用程序域可以确保在一个域中运行的代码不会影响进程中的其他应用程序。
3. 能够在不停止整个进程的情况下停止单个应用程序。
4. 使用应用程序域时,可以卸载在单个应用程序中运行的代码。
5. 在一个应用程序中运行的代码不能直接访问其他应用程序中的代码或资源。
为了强制实施此隔离,公共语言运行库禁止在不同应用程序域中的对象之间进行直接调用。要在各域之间传递对象,可以通过复制这些对象,或通过代理访问这些对象。如果复制对象,那么对该对象的调用为本地调用。也就是说,调用方和被引用的对象位于同一应用程序域中。如果通过代理访问对象,那么对该对象的调用为远程调用。在此情况下,调用方和被引用的对象位于不同的应用程序域中。域间调用所采用的远程调用基础结构与两个进程间的调用或两台计算机间的调用的基础结构相同。因此,被引用的对象的元数据必须对于两个应用程序域均可用,以便用 JIT 正确编译该方法调用。如果调用域对被调用对象的元数据没有访问权,则编译可能失败,并引发类型为 System.IO.FileNotFound 的异常。
1. 代码行为的作用范围由它运行所在的应用程序决定。
换言之,应用程序域将提供应用程序版本策略等配置设置、它所访问的任意远程程序集的位置,以及加载到该域中的程序集的位置信息。
2. 向代码授予的权限可以由代码运行所在的应用程序域来控制。
1.2 创建应用程序域
.NET提供了相关的类和方法来获取当前应用程序域的基本信息,也提供了创建和配置应用程序域的成员。其中,AppDomain 类是应用程序域的编程接口,此类包括各种方法,这些方法可以创建和卸载域、创建域中各类型的实例以及注册各种通知(如应用程序域卸载)。对于应用程序域的卸载,将在第3.1.3节做介绍。
代码清单1-1演示了如何创建一个应用程序域。
代码清单1-1 创建应用程序域
class Program
{
static void Main(string[] args)
{
AppDomain myDomain= AppDomain.CreateDomain("xuanhunDomain");//创建名为xuanhunDomain的应用程序域
Console.WriteLine("myDomain name is :{0}",myDomain.FriendlyName);//输出创建的程序域名称
Console.WriteLine("当前程序域的名称是:{0}", AppDomain.CurrentDomain.FriendlyName);//输出当前程序域名称
Console.ReadKey();
}
}
输出结果如图1-1所示。
图1-1 输出应用程序域名称