细说进程、应用程序域与上下文之间的关系(二)—— 应用程序域

简介:

目录

一、进程的概念与作用

二、应用程序域

三、深入了解.NET上下文

四、进程应用程序域与线程的关系

 

二、应用程序域

使用.NET建立的可执行程序 *.exe,并没有直接承载到进程当中,而是承载到应用程序域(AppDomain)当中。应用程序域是.NET引入的一个新概念,它比进程所占用的资源要少,可以被看作是一个轻量级的进程。
在一个进程中可以包含多个应用程序域,一个应用程序域可以装载一个可执行程序(*.exe)或者多个程序集(*.dll)。这样可以使应用程序域之间实现深度隔离,即使进程中的某个应用程序域出现错误,也不会影响其他应用程序域的正常运作。

当一个程序集同时被多个应用程序域调用时,会出现两种情况:
第一种情况:CLR分别为不同的应用程序域加载此程序集。
第二种情况:CLR把此程序集加载到所有的应用程序域之外,并实现程序集共享,此情况比较特殊,被称作为Domain Neutral。

 

2.1 AppDomain的属性与方法

在System命名空间当中就存在AppDomain类,用管理应用程序域。下面是AppDomain类的常用属性:

属性 说明
ActivationContext 获取当前应用程序域的激活上下文。
ApplicationIdentity 获得应用程序域中的应用程序标识。
BaseDirectory 获取基目录。
CurrentDomain 获取当前 Thread 的当前应用程序域。
Id 获得一个整数,该整数唯一标识进程中的应用程序域。
RelativeSearchPath 获取相对于基目录的路径,在此程序集冲突解决程序应探测专用程序集。
SetupInformation 获取此实例的应用程序域配置信息。

表2.0

AppDomain类中有多个方法,可以用于创建一个新的应用程序域,或者执行应用程序域中的应用程序。

方法 说明
CreateDomain 创建新的应用程序域。
CreateInstance 创建在指定程序集中定义的指定类型的新实例。
CreateInstanceFrom 创建在指定程序集文件中定义的指定类型的新实例。
DoCallBack 在另一个应用程序域中执行代码,该应用程序域由指定的委托标识。
ExecuteAssembly 执行指定文件中包含的程序集。
ExecuteAssemblyByName 执行程序集。
GetAssemblies 获取已加载到此应用程序域的执行上下文中的程序集。
GetCurrentThreadId 获取当前线程标识符。
GetData 为指定名称获取存储在当前应用程序域中的值。
IsDefaultAppDomain 返回一个值,指示应用程序域是否是进程的默认应用程序域。
SetData 为应用程序域属性分配值。
Load 将 Assembly 加载到此应用程序域中。
Unload 卸载指定的应用程序域。

表2.1

AppDomain类中有多个事件,用于管理应用程序域生命周期中的不同部分。

事件 说明
AssemblyLoad 在加载程序集时发生。
AssemblyResolve 在对程序集的解析失败时发生。
DomainUnload 在即将卸载 AppDomain 时发生。
ProcessExit 当默认应用程序域的父进程存在时发生。
ReflectionOnlyAssemblyResolve 当程序集的解析在只反射上下文中失败时发生。
ResourceResolve 当资源解析因资源不是程序集中的有效链接资源或嵌入资源而失败时发生。
TypeResolve 在对类型的解析失败时发生。
UnhandledException 当某个异常未被捕获时出现。

表2.2

下面将举例详细介绍一下AppDomain的使用方式

 

2.2 在AppDomain中加载程序集

由表2.1中可以看到,通过CreateDomain方法可以建立一个新的应用程序域。
下面的例子将使用CreateDomain建立一个应用程序域,并使用Load方法加载程序集Model.dll。最后使用GetAssemblies方法,列举此应用程序域中的所有程序集。

         static void Main(string[] args)
         {
             var appDomain = AppDomain.CreateDomain("NewAppDomain");
             appDomain.Load("Model");
             foreach (var assembly in appDomain.GetAssemblies())
                 Console.WriteLine(string.Format("{0}\n----------------------------",
                     assembly.FullName));
             Console.ReadKey();
         }

运行结果

注意:当加载程序集后,就无法把它从AppDomain中卸载,只能把整个AppDomain卸载。

当需要在AppDomain加载可执行程序时,可以使用ExecuteAssembly方法。

AppDomain.ExecuteAssembly("Example.exe");

 

2.3 卸载AppDomain

通过Unload可以卸载AppDomain,在AppDomain卸载时将会触发DomainUnload事件。
下面的例子中,将会使用 CreateDomain建立一个名为NewAppDomain的应用程序域。然后建立AssemblyLoad的事件处理方法,在程序集加载时显示程序 集的信息。最后建立DomainUnload事件处理方法,在AppDomain卸载时显示卸载信息。

 1         static void Main(string[] args)
 2         {
 3             //新建名为NewAppDomain的应用程序域
4 AppDomain newAppDomain = AppDomain.CreateDomain("NewAppDomain"); 5 //建立AssemblyLoad事件处理方法
6 newAppDomain.AssemblyLoad += 7 (obj, e) => 8 { 9 Console.WriteLine(string.Format("{0} is loading!", e.LoadedAssembly.GetName())); 10 }; 11 //建立DomainUnload事件处理方法
12 newAppDomain.DomainUnload += 13 (obj, e) => 14 { 15 Console.WriteLine("NewAppDomain Unload!"); 16 }; 17 //加载程序集
18 newAppDomain.Load("Model"); 19 //模拟操作
20 for (int n = 0; n < 5; n++) 21 Console.WriteLine(" Do Work.......!"); 22 //卸载AppDomain
23 AppDomain.Unload(newAppDomain); 24 Console.ReadKey(); 25 }

运行结果

 

2.4 在AppDomain中建立程序集中指定类的对象

使用CreateInstance方法,能建立程序集中指定类的对像。但使用此方法将返回一个ObjectHandle对象,若要将此值转化为原类型,可调用Unwrap方法。
下面例子会建立Model.dll程序集中的Model.Person对象。

 namespace Test
 {
      public class Program
     {
          static void Main(string[] args)
          {
              var person=(Person)AppDomain.CurrentDomain
                           .CreateInstance("Model","Model.Person").Unwrap();
              person.ID = 1;
              person.Name = "Leslie";
              person.Age = 29;
              Console.WriteLine(string.Format("{0}'s age is {1}!",person.Name,person.Age));
              Console.ReadKey();
          }
     }
 }
 
 namespace Model
 {
     public class Person
     {
           public int ID
           {
               get;
               set;
           }
           public string Name
           {
                get;
                set;
           }
           public int Age
           {
                get;
                set;
           }
      }
 }

 
 

相关文章
|
存储 安全 算法
【C++智能指针 相关应用】深入探索C++智能指针:跨进程、动态库与最佳实践
【C++智能指针 相关应用】深入探索C++智能指针:跨进程、动态库与最佳实践
74 5
|
6月前
|
应用服务中间件 nginx Windows
windows下DOS命令杀掉Nginx应用进程
windows下DOS命令杀掉Nginx应用进程
|
5月前
|
负载均衡 JavaScript 算法
Node.js 多进程的概念、原理、优势以及如何使用多进程来提高应用程序的性能和可伸缩性
Node.js 多进程的概念、原理、优势以及如何使用多进程来提高应用程序的性能和可伸缩性
51 1
|
6月前
|
Linux
Linux杀死同一个应用的所有进程
Linux杀死同一个应用的所有进程
|
17天前
|
弹性计算 Dubbo Serverless
Serverless 应用引擎操作报错合集之阿里函数计算中,生成图片时进程卡住如何解决
Serverless 应用引擎(SAE)是阿里云提供的Serverless PaaS平台,支持Spring Cloud、Dubbo、HSF等主流微服务框架,简化应用的部署、运维和弹性伸缩。在使用SAE过程中,可能会遇到各种操作报错。以下是一些常见的报错情况及其可能的原因和解决方法。
21 3
|
13天前
|
Linux Shell 调度
【Linux系列】fork( )函数原理与应用详解——了解【父子进程及其特性】(代码演示,画图帮助理解,思维导图,精简)(11)
【Linux系列】fork( )函数原理与应用详解——了解【父子进程及其特性】(代码演示,画图帮助理解,思维导图,精简)(11)
|
2月前
|
消息中间件 缓存 监控
【C++ 观察者模式的应用】跨进程观察者模式实战:结合ZeroMQ和传统方法
【C++ 观察者模式的应用】跨进程观察者模式实战:结合ZeroMQ和传统方法
96 1
|
2月前
|
前端开发 Android开发 iOS开发
应用研发平台EMAS使用 aliyun-react-native-push 库接入推送和辅助通道,推送都可以收到,但是在App切到后台或者杀掉进程之后就收不到推送了,是需要配置什么吗?
【2月更文挑战第31天】应用研发平台EMAS使用 aliyun-react-native-push 库接入推送和辅助通道,推送都可以收到,但是在App切到后台或者杀掉进程之后就收不到推送了,是需要配置什么吗?
34 2
|
2月前
|
消息中间件 Linux API
Linux进程间通信(IPC) Linux消息队列:讲解POSIX消息队列在Linux系统进程间通信中的应用和实践
Linux进程间通信(IPC) Linux消息队列:讲解POSIX消息队列在Linux系统进程间通信中的应用和实践
32 1
Linux进程间通信(IPC) Linux消息队列:讲解POSIX消息队列在Linux系统进程间通信中的应用和实践
|
2月前
|
Java 调度 Windows
进程与线程应用
进程与线程应用
17 2