关于寄宿和AppDomain

微软开发CLR时,将它实现成包含在一个DLL中的COM服务器。

任何Windows应用程序都能寄宿(容纳)CLR。(简单来讲,就是CLR在一个DLL中,通过引用这个DLL,可以实现包含CLR)

CLR COM服务器初始化会创建一个默认AppDomain,这个AppDomain只有在进程终结时才会被销毁。

然而宿主程序还可以要求CLR创建额外的AppDomain。

因为创建进程开销很大,并且需要大量内存来虚拟化进程的地址空间。

所以人们就像可不可以在一个进程上运行多个程序呢。

于是就在进程上寄宿CLR,并除了AppDomain的概念。AppDomain是为了提供隔离而设计的。

当然原因不止如此,寄宿为应用程序提供了自定义和可扩展性的能力,然而这会导致一些恶意dll去破坏应用程序的数据结构和代码,还能利用安全上下文来访问本来无权访问的资源。

CLR的AppDomain可以解决这个问题,允许第三方的不受信任的代码在现有进程中运行,而CLR保证数据结构、代码和安全上下文不被滥用和破坏

AppDomain,看名字就知道:应用程序域。

以下为AppDomain的具体功能:

  • 一个AppDomain的代码不能访问另一个AppDomain的代码创建的对象。这样就将两个AppDomain隔离开来,这种隔离使AppDomain很容易在进程中卸载,不会影响其它AppDomain正在运行的代码。
  • AppDomain可以卸载。(前面提到过,默认的第一个AppDomain是不能卸载的)
  • AppDomian可以单独保护。(每个AppDomain都会有自己的权限集)
  • AppDomain可以单独配置。(每个AppDomain都会有自己的配置设置,主要影响CLR在AppDomain中的加载方式。涉及搜索路径、版本绑定重定向、卷影复制以及加载器优化)

一个进程上面运行一个CLR COM服务器,然后该CLR管理多个AppDomain,每个AppDomain可以有自己独立的程序。有的程序集是可以在AppDomain中共享的,比如MSCorLib.dll这种与.NET密不可分的类型,在CLR初始化时会被自动加载,有自己独有的loader堆去维护类型对象,且作为"AppDomain"中立的方式为所有AppDomain共享。

跨越AppDomain边界访问对象

前面讲到AppDomain就是为了隔离而设计的,且一个AppDomain的代码不能访问另一个AppDomain的代码。

然而要去做到也不是没有办法,为了实现两个AppDomain之间的通信。

按照AppDomain通信可以将类型分为三种:按引用封送类型,按值封送类型,完全不能封送的类型。

进程中可以有多个线程和多个AppDomain,然而它们不是一一对应的。

虽然一个线程一次只能执行一个AppDomain中的代码,但是一个线程可以执行一个AppDomain的代码后再去执行另一个AppDomain的代码,并且还可以查看自己在哪个AppDomain中。

然而这里由于感觉用不到关系,而且有点小复杂,所以就只领会了中心思想:

按引用封送:实际上就是AppDomain比如B传给另一个AppDomain比如A一个引用对象b,当执行b的函数时,实际上是线程又切回了B,调用完后再切回A。

按值封送:这个实际上就是将一个AppDomain中的对象序列化然后放到另一个AppDomain进行反序列化中。

卸载AppDomain

调用静态方法AppDomain.Unload即可。

卸载AppDomain会卸载其中的所有程序集,释放loader堆。

主要步骤:

  1. CLR挂起进程中执行过托管代码的所有线程
  2. 查看那些线程正在执行要卸载的AppDomain中的代码,有就强迫对应的线程抛出一个ThreadAbortException(线程中止异常)并恢复执行线程,这将导致执行遇到的所有的finally块以清理资源。如果没有代码捕捉到这个异常,那么finally就不会执行,但是线程会终止,但进程可继续运行。(其它所有未处理的异常我们在前面讲过会终止进程,而这里只会终止这个线程.
  3. 执行完第二步,所有的线程都会离开此AppDomain,CLR进入前面垃圾回收类似的标记阶段,标记垃圾。
  4. CLR强制执行垃圾回收,这些对象的Finalize方法被调用来正确清理占用的资源。
  5. CLR恢复所有线程的执行。

任何时候都只会有一个线程来调用Unload方法,不会有多个线程同时调用。

宿主如何使用AppDomain

控制台UI应用程序,NT Service应用程序,Windows窗体应用程序和WPF应用程序都是自寄宿(即自己容纳CLR)的应用程序。

它们都有托管exe文件,托管exe文件初始化进程后,会加载“垫片”(即MSCorEE.dll),垫片检查应用程序集的CLR头信息,决定加载哪个版本的CLR到进程中,CLR加载完后再次检查CLR头去茶砸后Main函数,然后调用该方法后程序才算真正启动起来。

再举一个例子,就拿ASP.NET来说,客户端请求一个Web应用程序时,如果是第一次请求,那么就ASP.NET要求CLR创建新的AppDomain,每个Web应用程序根据虚拟根目录来标识,然后让CLR将包含应用程序所公开类型的程序集加载到新的AppDomain中,创建实例,并调用其中方法。如果不是第一次请求就不会创建新的AppDomain。然而如果客户端请求不同的Web应用程序,也会创建新的AppDomain。貌似就说的是IIS里的那些不同的网站。

小总结:

到这一步,还是打算讲一下自己对这个东西的理解。

对于.NET的世界而言,都是在一个进程之上加载CLR(CLR COM服务器),然后在这个CLR上再加载不同的AppDomain。

对于我们平常写的那些简单用.net创建的程序如控制台程序,实际上也是在一个托管exe上再加载CLR,而此时会加载了默认的一个AppDomain。此exe可以作为一个宿主去加载更多的AppDomain,然而这就需要自己手动去加载了。

而对于那些不是.NET的非托管应用程序,也是可以加载CLR,而此时也会加载了默认的一个AppDomain,实际上它也可以作为一个宿主去加载更多的AppDomain。

可能有偏差,还望指正!

PS:

本章内容只择其精要写了一下,具体的AppDomain的玩法需要的时候再进一步深究。(话说回来,总有一种一辈子玩不到这个东西的感觉)

【C#进阶系列】22 CLR寄宿和AppDomain的更多相关文章

  1. C#进阶系列 ---- 《CLR via C#》

      [C#进阶系列]30 学习总结 [C#进阶系列]29 混合线程同步构造 [C#进阶系列]28 基元线程同步构造 [C#进阶系列]27 I/O限制的异步操作 [C#进阶系列]26 计算限制的异步操作 ...

  2. 第22章 CLR寄宿和AppDomain

    22.1 CLR寄宿 CLR Hosting(CLR 宿主)的概念:初始启动.Net Application时,Windows进程的执行和初始化跟传统的Win32程序是一样的,执行的还是非托管代码,只 ...

  3. 第二十二章 CLR寄宿和AppDomain

    1. 概念解析 CLR Hosting(CLR 宿主):初始启动.Net Application时,Windows进程的执行和初始化跟传统的Win32程序是一样的,执行的还是非托管代码,只不过由于PE ...

  4. CLR寄宿和AppDomain

    一.CLR寄宿 .net framework在windows平台的顶部允许.者意味着.net framework必须用windows能理解的技术来构建.所有托管模块和程序集文件必须使用windows ...

  5. 重温CLR(十六) CLR寄宿和AppDomain

    寄宿(hosting)使任何应用程序都能利用clr的功能.特别要指出的是,它使现有应用程序至少能部分使用托管代码编写.另外,寄宿还为应用程序提供了通过编程来进行自定义和扩展的能力. 允许可扩展性意味着 ...

  6. clr via c# clr寄宿和AppDomain (一)

    1 clr寄宿-----.net framework在windows平台的顶部允许.者意味着.net framework必须用windows能理解的技术来构建.所有托管模块和程序集文件必须使用wind ...

  7. WCF 4.0 进阶系列 -- 随笔汇总

    WCF4.0 进阶系列–前言 WCF4.0 进阶系列--第一章 WCF简介 WCF4.0进阶系列--第二章 寄宿WCF服务 WCF4.0进阶系列--第三章 构建健壮的程序和服务 WCF4.0进阶系列- ...

  8. Ext JS学习第十六天 事件机制event(一) DotNet进阶系列(持续更新) 第一节:.Net版基于WebSocket的聊天室样例 第十五节:深入理解async和await的作用及各种适用场景和用法 第十五节:深入理解async和await的作用及各种适用场景和用法 前端自动化准备和详细配置(NVM、NPM/CNPM、NodeJs、NRM、WebPack、Gulp/Grunt、G

    code&monkey   Ext JS学习第十六天 事件机制event(一) 此文用来记录学习笔记: 休息了好几天,从今天开始继续保持更新,鞭策自己学习 今天我们来说一说什么是事件,对于事件 ...

  9. C#进阶系列——WebApi 接口返回值不困惑:返回值类型详解

    前言:已经有一个月没写点什么了,感觉心里空落落的.今天再来篇干货,想要学习Webapi的园友们速速动起来,跟着博主一起来学习吧.之前分享过一篇 C#进阶系列——WebApi接口传参不再困惑:传参详解  ...

随机推荐

  1. HTML和CSS经典布局5

    如下图: 需求: 1. 如图 2. 可以从body标签开始. 3. 页面内容高度设置高点,把窗口的滚动条显示出来,但是busy indicator不滚动. <!DOCTYPE html> ...

  2. ASP.Net请求处理机制初步探索之旅 - Part 1 前奏

    开篇:ASP.Net是一项动态网页开发技术,在历史发展的长河中WebForm曾一时成为了ASP.Net的代名词,而ASP.Net MVC的出现让这项技术更加唤发朝气.但是,不管是ASP.Net Web ...

  3. SQL Server 系统数据库恢复

    标签:SQL SERVER/MSSQL SERVER/数据库/DBA/故障恢复/master 概述 SQL Server 维护一组系统级数据库(称为“系统数据库”),这些数据库对于服务器实例的运行至关 ...

  4. Android学习——windows下搭建Cygwin环境

    在上一篇博文<Android学习——windows下搭建NDK_r9环境>中,我们详细的讲解了在windows下进行Android NDK开发环境的配置,我们也讲到了在NDk r7以后,我 ...

  5. [Unity3D]自己动手重制坦克舰队ArmadaTank

    [Unity3D]自己动手重制坦克舰队ArmadaTank 我玩过一款坦克游戏ArmadaTank(坦克舰队),如下图所示 几个月前我尝试用Unity3D重制这款游戏,已经可以玩起来了.下面是在PC上 ...

  6. [ASP.NET MVC 小牛之路]16 - Model 验证

    上一篇博文 [ASP.NET MVC 小牛之路]15 - Model Binding 中讲了MVC在Model Binding过程中如何根据用户提交HTTP请求数据创建Model对象.在实际的项目中, ...

  7. 我如何介绍 Microservice

    这篇文章转自我的 Github blog 一天我司招财猫姐(HR 大人)问我,你给我解释一下 Microservice 是什么吧.故成此文.一切都是从一个创业公司开始的. 故事 最近的创业潮非常火爆, ...

  8. 《Entity Framework 6 Recipes》中文翻译系列 (37) ------ 第六章 继承与建模高级应用之独立关联与外键关联

    翻译的初衷以及为什么选择<Entity Framework 6 Recipes>来学习,请看本系列开篇 6-13  在基类中应用条件 问题 你想从一个已存在的模型中的实体派生一个新的实体, ...

  9. Java接口和抽象类的区别

    今天看到项目中,写了一个抽象类,里面有很多方法继承了这类,当调用这个接口时,采用的是这个抽象类去调方法的,当时一想,这个不就是我们说的Java的多态的特征: 继承:存在继承关系的子类和父类 重写:子类 ...

  10. JAVA基础-输入输出:1.编写TextRw.java的Java应用程序,程序完成的功能是:首先向TextRw.txt中写入自己的学号和姓名,读取TextRw.txt中信息并将其显示在屏幕上。

    1.编写TextRw.java的Java应用程序,程序完成的功能是:首先向TextRw.txt中写入自己的学号和姓名,读取TextRw.txt中信息并将其显示在屏幕上. package Test03; ...