C#学习笔记----AppDomain应用程序域
使用.Net建立的可执行程序*.exe,并没有直接承载到进程当中,而是承载到应用程序域(AppDomain)当中。应用程序域是.Net引入的一个新概念,它比进程所占用的资源要少,可以被看做是一个轻量级的进程。一个应用程序域可以有多个线程,一个线程也可以穿梭于多个应用程序域。
在一个进程中可以包含多个应用程序域,一个应用程序域可以装在一个可执行程序(*.exe)或者多个程序集(*.dll)。这样可以使应用程序域之间实现深度隔离,即使进程中的某个应用程序域出现错误,也不会影响其他应用程序域的正常运作。
当一个程序集同时被多个应用程序域调用时,会出现两种情况:
- CLR分别为不同的应用程序域加载此程序集。
- CLR把此程序集加载到所有的应用程序域之外,并实现程序集共享,此情况比较特殊,被称作为Domain Neutarl。
应用程序域:(Application Domain,简称App Domain)一组程序集的一个逻辑容器,进程中的一个逻辑分区。通常由运行时宿主创建和操作。AppDomain唯一的作用就是进行隔离。
具体功能:
- 隔离,一个AppDomain中的代码创建的对象不能由另一个AppDomain中的代码直接访问。达到隔离应用程序的效果。当然如果要访问别的AppDomain中的内容,可以使用“按引用封送”或者“按值封送”的语义。
- AppDomain可以卸载,但不能卸载单独的程序集或类型,只能卸载整个应用程序域。从而卸载包含在该AppDomain中的所有程序集。
- AppDomain可以单独保护,AppDomain在创建后,会应用一个权限集,它决定了向这个AppDomain中运行的程序集授予的最大权限。从而保护宿主加载的代码不被破坏。
- 可以单独实施配置,AppDomain在创建后,会关联一组配置设置。这些设置主要影响CLR在AppDomain中加载程序集的方式。这些设置涉及搜索路径、版本重定向、卷影复制以及加载器优化。
- 需要隔离的程序集,譬如一些特别容易引起崩溃的代码可以考虑单独运行于一个特定的 appDomain;
- 不同安全级别的程序集,如果需要为自己的代码划分安全执行的边界,可以考虑将不同安全级别的代码单独创建于某个设定了不同安全信息的 appDomain
- 从性能上考虑,有些程序集可能会消耗大量资源,尽管在托管环境下,基本上不存在资源消耗漏洞,但是总会存在特定时间访问密集造成消耗大量资源的情况,这时可以考虑创建单独的 appDomain ,在资源消耗超过临界点后进行 appDomain 的卸载,适应系统运行要求。 Asp.net 中利用不同的appDomain 来提供支持就是为了防止一个应用程序的崩溃影响其他 asp.net 应用程序,同时 , 在不重新启动的系统不重新启动 IIS 不影响 asp.net 自身服务提供的情况下将一个 appDomain 卸掉同时启动新的 appDomain ,理想情况下可以实现 web 系统的长时间在线(这以往是昂贵的 unix 的特性,终于被 MS “借鉴”了)。
- 不同版本的同一应用程序集的同时运行。这个在 COM 时代是一个大问题,现在通过 appDomain ,实现了在一个进程中执行版本不同的两个程序集,可以做到良好的兼容性。
- 动态加载一些程序。
一、AppDomain的属性与方法
在System命名空间下就存在AppDomain类,用于管理应用程序域。
AppDomain的常用属性:
| 属性 | 说明 |
| ActivationContext | 获取当前应用程序域的激活上下文。 |
| ApplicationIdentity | 获得应用程序域中的应用程序标识。 |
| BaseDirectory | 获取基目录。 |
| CurrentDomain | 获取当前 Thread 的当前应用程序域。 |
| Id | 获得一个整数,该整数唯一标识进程中的应用程序域。 |
| RelativeSearchPath | 获取相对于基目录的路径,在此程序集冲突解决程序应探测专用程序集。 |
| SetupInformation | 获取此实例的应用程序域配置信息。 |
AppDomain的常用方法:
| 方法 | 说明 |
| CreateDomain | 创建新的应用程序域。 |
| CreateInstance | 创建在指定程序集中定义的指定类型的新实例。 |
| CreateInstanceFrom | 创建在指定程序集文件中定义的指定类型的新实例。 |
| DoCallBack | 在另一个应用程序域中执行代码,该应用程序域由指定的委托标识。 |
| ExecuteAssembly | 执行指定文件中包含的程序集。 |
| ExecuteAssemblyByName | 执行程序集。 |
| GetAssemblies | 获取已加载到此应用程序域的执行上下文中的程序集。 |
| GetCurrentThreadId | 获取当前线程标识符。 |
| GetData | 为指定名称获取存储在当前应用程序域中的值。 |
| IsDefaultAppDomain | 返回一个值,指示应用程序域是否是进程的默认应用程序域。 |
| SetData | 为应用程序域属性分配值。 |
| Load | 将 Assembly 加载到此应用程序域中。 |
| Unload | 卸载指定的应用程序域。 |
AppDomain事件:
| 事件 | 说明 |
| AssemblyLoad | 在加载程序集时发生。 |
| AssemblyResolve | 在对程序集的解析失败时发生。 |
| DomainUnload | 在即将卸载 AppDomain 时发生。 |
| ProcessExit | 当默认应用程序域的父进程存在时发生。 |
| ReflectionOnlyAssemblyResolve | 当程序集的解析在只反射上下文中失败时发生。 |
| ResourceResolve | 当资源解析因资源不是程序集中的有效链接资源或嵌入资源而失败时发生。 |
| TypeResolve | 在对类型的解析失败时发生。 |
| UnhandledException | 当某个异常未被捕获时出现。 |
二、在AppDomain中加载程序集
通过CreateDomain方法可以建立一个新的应用程序域。
下面给出一个使用CreateDomain建立一个应用程序域,并使用Load方法加载程序集Model.dll。
最后使用GetAssemblies方法,列举此应用程序域中的所有程序集。

public class Program
{
static void Main(string[] args)
{
var domain = AppDomain.CreateDomain("MyAppDomain");
domain.Load(@"控制台 - 学习测试");
foreach (var assembly in domain.GetAssemblies())
{
Console.WriteLine(assembly.FullName);
} Console.ReadKey();
}
}

输出结果如下:

注意:当加载程序集后,就无法把它从AppDomain中卸载,只能把整个AppDomain卸载。
当需要在AppDomain加载可执行程序时,可以使用ExecuteAssembly方法。
如,建一个控制台程序:

class Program
{
static void Main(string[] args)
{
Console.WriteLine("供应用程序域执行!");
Console.ReadKey();
}
}

将上面程序生成的路径保存到:C:\Users\ChenZhuo\Desktop\ConsoleApplication1\ConsoleApplication1\bin\Debug\ConsoleApplication1.exe
下面我们创建一个应用程序域并执行上面那个程序集:

public class Program
{
static void Main(string[] args)
{
var domain = AppDomain.CreateDomain("MyAppDomain");
//执行指定的程序集
domain.ExecuteAssembly(@"C:\Users\ChenZhuo\Desktop\ConsoleApplication1\ConsoleApplication1\bin\Debug\ConsoleApplication1.exe");
Console.ReadKey();
}
}

输出结果如下:

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

class Program
{
static void Main(string[] args)
{
//新建一个应用程序域
AppDomain MyDomain = AppDomain.CreateDomain("domain");
//建立AssemblyLoad事件处理方法
MyDomain.AssemblyLoad += (sender, e) =>
{
Console.WriteLine("程序集正在加载!" + e.LoadedAssembly.FullName);
};
//建立AssemblyUnload事件处理方法
MyDomain.DomainUnload += (sender, e) =>
{
Console.WriteLine("程序集正在卸载!");
};
//加载程序集
MyDomain.Load("MySpace");
Thread.Sleep(1000);
Console.WriteLine("正在工作中!");
//卸载程序集
AppDomain.Unload(MyDomain); Console.ReadKey();
}
}

输出结果如下:

四、在AppDomain中建立程序集中指定类的对象
使用CreateInstance方法,能建立程序集中指定类的对象。但使用此方法将返回一个ObjectHandle对象,若要将此值转换为原类型,可调用UnWrap方法。
下面例子利用MySpace.dll程序集中的MySpace.Person对象。

namespace ConsoleApplication1
{
public class Program
{
static void Main(string[] args)
{
var person = (Person)AppDomain.CurrentDomain.CreateInstance("MySpace", "MySpace.Person").Unwrap();
person.Id = 1;
person.Name = "张飞";
Console.WriteLine(person.Id + " : " + person.Name); Console.ReadKey();
}
}
}

Person:

namespace MySpace
{
public class Person
{
public int Id { get; set; }
public string Name { get; set; }
}
}

输出结果如下:

C#学习笔记----AppDomain应用程序域的更多相关文章
- 【WPF】学习笔记(三)——这个家伙跟电子签名板有个约定
这篇博客依旧是以电子签名板为基础而展开的,主要是对前文([WPF]学习笔记(一)--做一个简单的电子签名板)存在的部分问题进行解释,以及部分小功能的添加.由于这篇博客是建立在学习笔记一的基础上的,所以 ...
- .NET Remoting学习笔记(三)信道
目录 .NET Remoting学习笔记(一)概念 .NET Remoting学习笔记(二)激活方式 .NET Remoting学习笔记(三)信道 参考:♂风车车.Net .NET Framework ...
- .NET Remoting学习笔记(一)概念
目录 .NET Remoting学习笔记(一)概念 .NET Remoting学习笔记(二)激活方式 .NET Remoting学习笔记(三)信道 背景 自接触编程以来,一直听过这个名词Remotin ...
- C#学习笔记——面向对象、面向组件以及类型基础
C#学习笔记——面向对象.面向组件以及类型基础 目录 一 面向对象与面向组件 二 基元类型与 new 操作 三 值类型与引用类型 四 类型转换 五 相等性与同一性 六 对象哈希码 一 面向对象与面向组 ...
- Asp.Net 学习笔记(IIS不同版本和Asp.Net)
主要目的是在网上记录一下学习笔记,如有不对,请指出 谢谢!! iis5.x: 存在问题,inet info收到动态请求后,aspnt_isapi.dll会被加载到inetinfo.exe(挂载w3sv ...
- 【转载】.NET Remoting学习笔记(三)信道
目录 .NET Remoting学习笔记(一)概念 .NET Remoting学习笔记(二)激活方式 .NET Remoting学习笔记(三)信道 参考:♂风车车.Net .NET Framework ...
- 【转载】.NET Remoting学习笔记(一)概念
目录 .NET Remoting学习笔记(一)概念 .NET Remoting学习笔记(二)激活方式 .NET Remoting学习笔记(三)信道 背景 自接触编程以来,一直听过这个名词Remotin ...
- Unity(IOC)学习笔记
原文:Unity(IOC)学习笔记 版权声明:本文为博主原创文章,未经博主允许不得转载. https://blog.csdn.net/m0_37591671/article/details/79432 ...
- Orleans[NET Core 3.1] 学习笔记(三)( 3 )服务端配置
服务端配置 Silo通过SiloHostBuilder和许多补充选项类以编程方式进行配置. Silo配置有几个关键方面: Orleans集群信息 集群提供程序(不知道咋翻译) Silo到Silo和Cl ...
随机推荐
- tfw格式图解
话不多说,直接看图. 上图中的UV坐标,实际上只的是图像的 横向坐标 和 纵向坐标 .即图像的行和列坐标. 对于图上任意一个像素点(col,row)这个坐标,换算其地理坐标就十分简单. GeoX = ...
- 15 BasicHashTable基本哈希表类(二)——Live555源码阅读(一)基本组件类
这是Live555源码阅读的第一部分,包括了时间类,延时队列类,处理程序描述类,哈希表类这四个大类. 本文由乌合之众 lym瞎编,欢迎转载 http://www.cnblogs.com/oloroso ...
- SQL Server 2008 R2 Developer (x86, x64, ia64) – DVD (Chinese-Simplified)
http://blog.sina.com.cn/s/blog_4aedf6370101j9tz.html 1. SQL Server 2008 R2 Developer (x86, x64, ia64 ...
- [k]css盒模型
box-sizing : content-box || border-box || inherit 1.content-box:此值为其默认值.元素的宽度/高度(width/height)等于元素边 ...
- TCP三次握手、四次挥手及状态转换图
TCP/IP通信的三次握手如下: TCP是主机对主机层的传输控制协议,提供可靠的连接服务: 位码即tcp标志位,有6种标示:SYN(synchronous建立联机) .ACK(acknowledgem ...
- Light OJ 1140
数位dp,需要记录前导0. 数位dp中需要注意统计0,00,000……这些数字. 数位dp的写法可以分为两类.由于我们通常采用记忆化搜索的方式进行dp,所以我们有一个记忆化数组. 一种是记忆化数组的意 ...
- oracle 学习
一.数据库语言部分1. SQL语言:关系数据库的标准语言2. PL/SQL:过程化语言Procedural Language3. SQL*Plus:简单的报表,操作系统接口 4. Oracle 8.0 ...
- ffmpeg-20160806-bin.7z
ESC 退出 0 进度条开关 1 屏幕原始大小 2 屏幕1/2大小 3 屏幕1/3大小 4 屏幕1/4大小 S 下一帧 [ -2秒 ] +2秒 ; -1秒 ' +1秒 下一个帧 -> -5秒 f ...
- 4.kvm克隆虚拟机
virt-clone 作用简介 virt-clone 主要是用来克隆kvm虚拟机,并且通过 Options.General Option.Storage Configuration.Networkin ...
- nyoj116_士兵杀敌(二)_树状数组
士兵杀敌(二) 时间限制:1000 ms | 内存限制:65535 KB 难度:5 描述 南将军手下有N个士兵,分别编号1到N,这些士兵的杀敌数都是已知的. 小工是南将军手下的军师,南将军经常 ...