`
javatgo
  • 浏览: 1122409 次
  • 性别: Icon_minigender_2
  • 来自: 北京
文章分类
社区版块
存档分类
最新评论

关于appdomain, assembly, 进程,线程的概念体会

阅读更多
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;
}
}
}

注意:

1. 要想让一个对象能够穿过AppDomain边界,必须要继承MarshalByRefObject类,否则无法被其他AppDomain使用。

2. 每个线程都有一个默认的AppDomain,可以通过Thread.GetDomain()来得到

分享到:
评论

相关推荐

    新建AppDomain中捕获异常

    在AppDomain捕获异常并处理的例子,详见blog.csdn.net/fuadam/

    Visual Basic.NET线程参考手册

    第1章 定义线程 1.1 线程的定义 1.1.1 多任务 1.1.2 进程 1.1.3 线程 1.2 Visual Basic.NET对线程的支持 1.2.1 System.AppDomain类 1.2.2 线程管理与.NET运行库 1.3 本章小结第2章 .NET中的线程 2.1 System....

    AppDomain编程

    关于AppDomain编程的全面资料,适合中高级技术人员阅读

    多线程学习文档

    进程(Process)是Windows系统中的一个基本概念,它包含着一个运行程序所需要的资源。进程之间是相对独立的,一个进程无法访问另一个进程的数据(除非利用分布式计算方式),一个进程运行的失败也不会影响其他进程的...

    AppDomain动态加载范例

    范例 Appdomain动态加载及数据交互范例

    微软操作系统进程管理神器

    显示运行.NET应用的进程,以及与.NET相关的细节(比如应用域(AppDomain〕的列表、已加载的程序集和CLR性能计数器)。 显示进程和线程的启动时间。 显示内存映射文件(不仅仅包括DLL)的完整列表。 能够挂起进程...

    cpp-将CEXE或DLL程序集注入其他进程的每个CLR运行时和AppDomain

    将C#EXE或DLL程序集注入其他进程的每个CLR运行时和AppDomain

    AssemblyDynamicLoader.rar_CorBindToRuntimeEx_appdomain_宿主应用程序

    运行一个.NET应用程序或者运行库宿主时,OS会首先建立一个进程,然后会在进程中加载CLR(这个加载一般是通过调用_CorExeMain或者_CorBindToRuntimeEx方法来实现),在加载CLR时会创建一个默认的AppDomain,它是CLR的...

    CrossAppDomainWCF:这只是关于通过 WCF 和 NamedPipes 进行跨 AppDomain 通信的概念验证

    这只是关于通过 WCF 和 NamedPipes 进行跨 AppDomain 通信的概念验证。 主要项目是 PoC.AppDomainWCF.App,它承载 WCF 服务并包含 Manager 类以创建新的 AppDomains 并将程序集加载到其中。 PoC.AppDomainWCF....

    C#综合细说进程、应用程序域与上下文

    本文主要是介绍进程(Process)、应用程序域(AppDomain)、.NET上下文(Context)的概念与操作。虽然在一般的开发当中这三者并不常用,但熟悉三者的关系,深入了解其作用,对提高系统的性能有莫大的帮助。在本篇...

    将C#EXE或DLL程序集注入每个CLR运行时和另一个进程的AppDomain中。-C/C++开发

    clrinject将C#EXE或DLL程序集注入任何其他进程的CLR运行时和AppDomain中。 然后,注入的程序集可以访问注入者进程的类的静态实例,从而影响其内部状态。 clrinject将C#EXE或DLL程序集注入任何其他进程的CLR运行时...

    .net序列化技术详解

    序列化和反序列化我们可能经常会听到,其实通俗一点的解释,...序列化和反序列化最主要的作用有:1、在进程下次启动时读取上次保存的对象的信息 2、在不同的AppDomain或进程之间传递数据 3、在分布式应用系统中传递数据

    C#中动态加载和卸载DLL

    C#也提供了实现动态卸载DLL的方法,通过AppDomain来实现。AppDomain是一个独立执行应用程序的环境,当AppDomain被卸载的时候,在该环境中的所有资源也将被回收。

    Unity 独立配置文件Demo

    var unityConfig = System.AppDomain.CurrentDomain.BaseDirectory + @"App_Data\unity.config"; var fileMap = new ExeConfigurationFileMap() { ExeConfigFilename = unityConfig }; var configuration = ...

    MEFInAnAppDomain:演示在AppDomain中使用MEF并允许在应用程序运行时交换MEF零件

    MEF在AppDomain中演示在AppDomain中使用MEF并允许在应用程序运行时交换MEF零件。 这是我有关此主题的博客条目的源代码:和文章:

    C#实现DLL热插拔

    使用AppDomain实现不重启进程的dll的重复加载

    CLR via C# 中文版 第三版(part1)

    本书分为五个部分:    第一部分,CLR基础(CLR ... 第五部分,线程(Threading),这是第三版新增加的内容,包括线程基础,计算密集的异步操作,I/O密集的异步操作,基本的线程同步构造,混合的线程同步构造等。

    CLR via C# 中文版 第三版(part2)

    本书分为五个部分:    第一部分,CLR基础(CLR ... 第五部分,线程(Threading),这是第三版新增加的内容,包括线程基础,计算密集的异步操作,I/O密集的异步操作,基本的线程同步构造,混合的线程同步构造等。

    .NET 动态加载DLL文件

    目前对于 Assembly, CLR 没有提供卸载 Assembly 的方法。而 Assembly 是 驻留在 Appdomain 中,Appdomain 是可以动态卸载和创建的。

    使用AppDomain加载和卸载程序集的细微差别

    考虑使用可热插拔模块编写应用程序时应了解的事项。

Global site tag (gtag.js) - Google Analytics