AppDomain是CLR的运行单元,它可以加载Assembly、创建对象以及执行程序。
  AppDomain是CLR实现 代码隔离 的基本机制。
  每一个AppDomain可以单独运行、停止;每个AppDomain有自己默认的异常处理;一个AppDomain的运行失败不会影响到其他的AppDomain。
  CLR在被CLR Host(windows shell or InternetExplorer or SQL Server)加载后,要创建一个默认的AppDomain,程序的入口点(Main方法)就是在这个默认的AppDomain中执行。
  1.AppDomain vs 进程
AppDomain被创建在进程中,一个进程内可以有多个AppDomain。一个AppDomain只能属于一个进程。
  2.AppDomain vs 线程
其实两者本来没什么好对比的。AppDomain是个静态概念,只是限定了对象的边界;线程是个动态概念,它可以运行在不同的AppDomain。一个AppDomain内可以创建多个线程,但是不能限定这些线程只能在本AppDomain内执行代码。
  CLR中的System.Threading.Thread对象其实是个soft thread,它并不能被操作系统识别;操作系统能识别的是hard thread。一个soft thread只属于一个AppDomain,穿越AppDomain的是hard thread。当hard thread访问到某个AppDomain时,一个AppDomain就会为之产生一个soft thread。hard thread有thread local storage(TLS),这个存储区被CLR用来存储这个hard thread当前对应的AppDomain引用以及soft thread引用。当一个hard thread穿越到另外一个AppDomain时,TLS中的这些引用也会改变。当然这个说法很可能是和CLR的实现相关的。
  3.AppDomain vs Assembly
Assembly是.Net程序的基本部署单元,它可以为CLR提供用于识别类型的元数据等等。Assembly不能单独执行,它必须被加载到AppDomain中,然后由AppDomain创建程序集中的对象。一个Assembly可以被多个AppDomain加载,一个AppDomain可以加载多个Assembly。每个AppDomain引用到某个类型的时候需要把相应的assembly在各自的AppDomain中初始化。因此,每个AppDomain会单独保持一个类的静态变量。
  4.AppDomain vs 对象
任何对象只能属于一个AppDomain。AppDomain用来隔离对象,不同AppDomain之间的对象必须通过Proxy(reference type)或者Clone(value type)通信。
引用类型需要继承System.MarshalByRefObject才能被Marshal/UnMarshal(Proxy)。
值类型需要设置Serializable属性才能被Marshal/UnMarshal(Clone)。
  5.AppDomain vs Assembly Code
AppDomain和程序集的源代码是什么关系呢?每个程序集的代码会分别装载到各个AppDomain中?
首先我们要把程序集分3类
1.mscorlib,这是每个.net程序都要引用到的程序集。
2.GAC,这个是强命名的公用程序集,可以被所有的.net程序引用。
3.Assembly not in GAC,这是普通的assembly,可以不是强命名,不放到GAC中。
启动CLR,进入entry point时可以设置LoaderOptimization属性:
[LoaderOptimization(LoaderOptimization.MultiDomain]
static void Main()
{...}
LoaderOptimization属性可以设置三个不同的枚举值,来设置针对前面说的三种程序集的代码存放以及访问方式。
LoaderOptimization Enumeration/Attribute

Value Expected Domains in Process Each Domain Expected to Run ... Code for MSCORLIB Code for Assemblies in GAC Code for Assemblies not in GAC
SingleDomain One N/A Per-process Per-domain Per-domain
MultiDomain Many Same Program Per-process Per-process Per-process
MultiDomainHost Many Different Programs Per-process Per-process Per-domain

1.SingleDomain,由于只启动一个AppDomain,那么code就被直接装载到了AppDomain中,访问静态变量更快捷。

2.MultiDomain,所有的Assembly代码是进程级别的,因此所有的AppDomain只访问一份代码。这大大减少了程序占用的内存,但
是由于程序集的静态变量仍然在各个AppDomain中,因此代码访问静态变量需要先得到AppDomain的引用再进行转换,速度会受到
影响。
3.MultiDomainHost,只有GAC代码是共享的,非GAC的Assembly依然会加载到被使用的AppDomain中,这样提高了静态变量的访问
速度,当然也增加了程序占用的内存。 
 
不管是哪种方式,mscorlib始终是process级别的,即只有一份mscorlib代码在内存中。

C#中动态加载和卸载DLL

在C++中加载和卸载DLL是一件很容易的事,LoadLibrary和FreeLibrary让你能够轻易的在程序中加载DLL,然后在任何地方 卸载。在C#中我们也能使用Assembly.LoadFile实现动态加载DLL,但是当你试图卸载时,你会很惊讶的发现Assembly没有提供任何 卸载的方法。这是由于托管代码的自动垃圾回收机制会做这件事情,所以C#不提供释放资源的函数,一切由垃圾回收来做。

这引发了一个问题,用Assembly加载的DLL可能只在程序结束的时候才会被释放,这也意味着在程序运行期间无法更新被加载的DLL。而这个功能在某 些程序设计时是非常必要的,考虑你正在用反射机制写一个查看DLL中所有函数详细信息的程序,程序提供一个菜单让用户可以选择DLL文件,这时就需要让程 序能够卸载DLL,否则一旦用户重新得到新版本DLL时,必须要重新启动程序,重新选择加载DLL文件,这样的设计是用户无法忍受的。

C#也提供了实现动态卸载DLL的方法,通过AppDomain来实现。AppDomain是一个独立执行应用程序的环境,当AppDomain被卸载的 时候,在该环境中的所有资源也将被回收。关于AppDomain的详细资料参考MSDN。下面是使用AppDomain实现动态卸载DLL的代码,

using System;
using System.Collections.Generic;
using System.Text;
using System.Threading;
using System.Reflection;
namespace UnloadDll
{
class Program
{
static void Main(string[] args)
{
string callingDomainName = AppDomain.CurrentDomain.FriendlyName;//Thread.GetDomain().FriendlyName;
Console.WriteLine(callingDomainName);
AppDomain ad = AppDomain.CreateDomain("DLL Unload test");
ProxyObject obj = (ProxyObject)ad.CreateInstanceFromAndUnwrap(@"UnloadDll.exe", "UnloadDll.ProxyObject");
obj.LoadAssembly();
obj.Invoke("TestDll.Class1", "Test", "It's a test");
AppDomain.Unload(ad);
obj = null;
Console.ReadLine();
}
}

class ProxyObject : MarshalByRefObject
{
Assembly assembly = null;
public void LoadAssembly()
{
assembly = Assembly.LoadFile(@"TestDLL.dll");
}
public bool Invoke(string fullClassName, string methodName, params Object[] args)
{
if(assembly == null)
return false;
Type tp = assembly.GetType(fullClassName);
if (tp == null)
return false;
MethodInfo method = tp.GetMethod(methodName);
if (method == null)
return false;
Object obj = Activator.CreateInstance(tp);
method.Invoke(obj, args);
return true;
}
}
}

AppDOMain(摘录)的更多相关文章

  1. C#.Net 如何动态加载与卸载程序集(.dll或者.exe)4-----Net下的AppDomain编程 [摘录]

    最近在对AppDomain编程时遇到了一个问题,卸载AppDomain后,在内存中还保留它加载的DLL的数据,所以即使卸载掉AppDomain,还是无法更新它加载的DLL.看来只有关闭整个进程来更新D ...

  2. MVC、MVP、MVVM、Angular.js、Knockout.js、Backbone.js、React.js、Ember.js、Avalon.js、Vue.js 概念摘录

    注:文章内容都是摘录性文字,自己阅读的一些笔记,方便日后查看. MVC MVC(Model-View-Controller),M 是指业务模型,V 是指用户界面,C 则是控制器,使用 MVC 的目的是 ...

  3. AppDomain对于静态对象的独享引用

    AppDomain可以理解为一个独立的沙箱,当有独立的第静态对象在appDomain中被访问时,会在appDomain中产生独立的内存对象.比如appDomain1 appDomain2同时对 静态对 ...

  4. AppDomain 详解(转)

    AppDomain是CLR的运行单元,它可以加载Assembly.创建对象以及执行程序. AppDomain是CLR实现代码隔离的基本机制. 每一个AppDomain可以单独运行.停止:每个AppDo ...

  5. 同一AppDomain内的SharpGL的FrameBuffer会相互影响?

    同一AppDomain内的SharpGL的FrameBuffer会相互影响? 今天做一个试验时,偶然发现了这样一个问题. 以SharpGL的示例项目SimpleDrawingSample为例. 给Fo ...

  6. C#中AppDomain.CurrentDomain.BaseDirectory及各种路径获取方法

    // 获取程序的基目录.System.AppDomain.CurrentDomain.BaseDirectory // 获取模块的完整路径,包含文件名System.Diagnostics.Proces ...

  7. 【C#进阶系列】22 CLR寄宿和AppDomain

    关于寄宿和AppDomain 微软开发CLR时,将它实现成包含在一个DLL中的COM服务器. 任何Windows应用程序都能寄宿(容纳)CLR.(简单来讲,就是CLR在一个DLL中,通过引用这个DLL ...

  8. Failed to create AppDomain 'xxx'. Exception has been Failed to create AppDomain

    一服务器上的数据库全部被置于紧急模式(EMERGENCY),在错误日志里面能看到大量下面的错误 Failed to create AppDomain "YourSQLDba.dbo[runt ...

  9. 《征服 C 指针》摘录1:什么是空指针?区分 NULL、0 和 '\0'

    一.什么是空指针? 空指针 是一个特殊的指针值. 空指针 是指可以确保没有向任何一个对象的指针.通常使用宏定义 NULL 来表示空指针常量值. 空指针 确保它和任何非空指针进行比较都不会相等,因此经常 ...

随机推荐

  1. 功放TAS5719耳机POP noise分析 对策

    驱动功放时,遇到POP noise 是常见的问题,以前遇到此问题,首先想到的对策就是mute the output.本人一直来对此种解法感觉不爽,心里不快.最近遇到开机时耳机有很强的POP,决定好好研 ...

  2. 【Java/Android性能优 4】PreloadDataCache支持预取的数据缓存,使用简单,支持多种缓存算法,支持不同网络类型,扩展性强

    本文转自:http://www.trinea.cn/android/preloaddatacache/ 本文主要介绍一个支持自动向前或向后获取新数据的缓存的使用及功能.Android图片内存缓存可见I ...

  3. 一位学长的学习建议(java方向)

    1.前台总得有个拿的出手的页面能力吧,ajax,jquery不说精通但是至少能看懂,能根据业务需求来改吧. 2.数据库方面至少得玩过mysql,DB2,Oracle中的两个以上吧.hibernate或 ...

  4. web调试的一些小技巧

    1.不带缓存的刷新,用于刷新css或者js:Ctrl+F5 待续...

  5. win10 U盘重装

    之前用一键重装软件装系统后,D盘留下了一个PE系统,后来我装双系统装好Ubuntu后,打开Ubuntu结果出现了那个PE系统,最后没办法只好重装win10. 重装系统主要有三种方法,参见:链接 因为电 ...

  6. java 代码优化

    Java程序中的内存管理机制是通过GC完成的,“一个对象创建后被放置在JVM的堆内存中,当永远不在应用这个对象的时候将会被JVM在堆内存中回收.被创建的对象不能再生,同时也没有办法通过程序语句释放”( ...

  7. 单例Singleton

    先提供一个完整版: // .h文件 @interface SingleTon : NSObject /** 获取单例对象 */ + (instancetype)sharedInstance; + (i ...

  8. celery:Unrecoverable error: AttributeError("'unicode' object has no attribute 'iteritems')

    环境描述 python2+django1.9下使用celery异步处理耗时请求. celery使用的是celery-with-redis这个第三方库,版本号为3.0. pip install cele ...

  9. 5-3 time模块

    1.取当前时间戳和当前格式化时间 import time1 # 以时间戳的形式打印当前时间 1543849862 print(int(time.time()))#时间戳 # 取当前格式化好的时间 20 ...

  10. js浮点数加减乘除

    浮点数精确计算 /** ** 加法函数,用来得到精确的加法结果 ** 说明:javascript的加法结果会有误差,在两个浮点数相加的时候会比较明显.这个函数返回较为精确的加法结果. ** 调用:ac ...