译者后记

译者后记 从事软件开发的人,都是耐得住寂寞的人。Jeffery 不仅耐的住寂寞,还在自己专业玲领域取得了很高的造诣。取得了很高的造诣不说,他还愿意将自己的心得与大家分享。愿意和大家分享不说,他还非常实诚,真心想把自己的全部知识都清楚地交待给读者。字里行间,全是殷殷叮嘱。无浮夸之文字,倾心血而写就,近十年之所悟,尽呈现于本书。 读完这本书,你的心灵会受到极大的震撼。原因很简单,以前许多似懂非懂的概念,现在变得清晰明了;以前自以为是的做法,现在得到彻底纠正;以前艰苦摸索的编程技巧,现在如同 1+1 一样简单。 Jeffrey 最擅长的就是把最基本的东西将清楚。你以前或许知道 1+1 等于 2,但他会把 1+1 为什么等于 2 讲的明明白白。最终你会有一种顿悟的感觉,然后自动地知道 1+2 等于几,2+2 等于几。不需要翻阅其他书籍来查询结果。 本书基于《CLR via C#》第 3 版,在保持上一版精华内容的同时进行了大量修订,并添加了大量关于 C# 5.0 新特性的内容。翻译这一版的过程中,我对上一版也进行了精校和勘误,许多勘误和改进意见都是由热心读者提交的。在此对他们表示衷心感谢!他们包括但不限于:56xue Castor DamnnnSure JeffFan Jeffrey You Kenny Wang LuckyDogFace,Neil,Titus,charlesgeorge, dream-like, fanfan, frank , hongkunjiang,huihui,kman,liu888bingsong,negy_liang,ooooo84,quark,sd,skyiv,wu,wukun0502,wzhou,yeahe83,北纬 49° 的雨,笨笨,不世出的 CLR 小白,大支豬舆小蘋果,何苦,来客心动,飘荡,飘飘白云,气象万千,千年一梦,如水的人生,施博,酸菜鱼,永远的阿哲 没有后期维护的书不算是好书。即使是本书英文原版,也维护了一份很长的勘误表,我本人也为其贡献良多。本书中文版将延续我一直以来坚持的风格,建立专门的页面进行维护,提供资源下载和勘误等服务。请大家继续前往我的博客(http://transbot.blog.163.com),发表关于本书的意见和建议。 本书翻译过程中,参与人员有柏红羽、陈绍云、成荣静、文天山、刁灿群、黄洁、江卫、蒋昌友、李建、刘其星、刘琼、刘勇、毛越龙、莫永红、文瑞、施玉梅、叶昌元、游美波、张攀飞和周建超。尤其要感谢我的乖女儿周子衿。人生的足迹,终于来到高中这一重要阶段,且行且珍惜。 最后,如同往常一样,我要说所有的功劳都要归于作者,所有的错误都要归于译者。欢迎大家批评指正。本书最后将列出我所采用的术语,以帮助大家进一步理解。 下表列出本书使用的一些术语,有异于 MSDN 文档(以后简称“文档”)的会专门指出。 术语 说明 (S)Byte 等同于“SByte” 和 “Byte”,这是作者喜欢的说法。类似的还有(U)Int16,(U)Int32,(U)IntPtr等 AppDomain (保留原文) Compute-Bound 和 I/O-Bound 计算限制和I/O限制(一个操作如果因为处理器和 I/O 的限制而不得不等待,就称为计算限制或 I/O限制的操作) Windows Store app Windows Store 应用(文档中翻译成“Windows 应用商店应用”),显得过于冗长 action method 操作方法 antecedent task 和 continuation task 前置任务和延续任务 arity 元数。在计算机编程中,一个函数或运算(操作)的元数是指函数获取的实参或操作数的个数。它源于像 unary(arity=1)、binary(arity=2)、ternary(arity=3)这样的单词 asynchronously synchronization 异步地同步(同步对资源的访问,但以异步方式进行,即不阻塞线程) atomic 原子性(读或写都是一次完成,别的线程看不到中间状态,就说这种读写是原子性的) attribute 特性(以文档为准) awaiter 等待者(调用 GetAwaiter 所返回的对象) bit flag 位标志 block 阻塞(停下来等着) callback 回调(回调方法简称为“回调”) calling thread 调用线程(发出调用的线程,也称主调线程) capture 捕捉(文档中主要用“捕捉”,偶尔用“捕获”) cast 转型(不用文档的“强制类型转换”是因为太冗长) compact 压缩(但此压缩非彼压缩,这里只是按照约定俗成的方式将 compact 翻译成“压缩”。不要以为”压缩“后内存会增多。相反,这里的”压缩“更接近于”碎片整理“。但事实上,从上个世纪 80 年开始,人们就把它看成是 compress 的近义词而翻译成”压缩“,以讹传讹至今) contract 文档的翻译非常混乱,包括协定、协议、合约、约定和契约等;本书使用”协定“ covariance 和 contravariance 协变和逆变(协变是指在要求使用一个类型的地方,能改为使用它的基类;逆变则是指在要求使用一个类型的地方,能改为使用它的派生类。C#用关键字 in 表示逆变量,用在输入位置;用 out 表示协变量,用在输出位置。详请参见 12....

2024-11-20 · 2 分钟 · SAM

第 30 章 混合线程同步构造

第 30 章 混合线程同步构造 本章内容 一个简单的混合锁 自旋、线程所有权和递归 FCL 中的混合结构 著名的双检锁技术 条件变量模式 异步的同步构造 并发集合类 第 29 章“基元线程同步构造”讨论了基元用户模式和内核模式线程同步构造。其他所有线程同步构造都基于它们而构建,而且一般都合并了用户模式和内核模式构造,我们称为混合线程同步构造。没有线程竞争时,混合构造提供了基元用户模式构造所具有的性能优势。多个线程竞争一个构造时,混合构造通过基元内核模式的构造来提供不“自旋”的优势(避免浪费 CPU 时间)。由于大多数应用程序的线程都很少同时竞争一个构造,所以性能上的增强可以使你的应用程序表现得更出色。 本章首先展示了如何基于构造来构建混合构造。然后展示了 FCL 自带的许多混合构造,描述了它们的行为,并介绍了如何正确使用它们。我还提供了一些我自己创建的构造,它们通过 Wintellect 的 Power Threading 库免费提供给大家使用,请从 http://wintellect.com/Resource-Power-Collections-Library 下载。 本章末尾展示了如何使用 FCL 的并发集合类来取代混合构造,从而最小化资源使用并提升性能。最后讨论了异步的同步构造,允许以同步方式访问资源,同时不造成任何线程的阻塞,从而减少了资源消耗,并提高了伸缩性。 30.1 一个简单的混合锁 言归正传,下面是一个混合线程同步锁的例子: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 internal sealed class SimpleHybridLock : IDisposable { // Int32 由基元用户模式构造 (Interlocked 的方法)使用 private Int32 m_waiters = 0; // AutoResetEvent 是基元内核模式构造 private readonly AutoResetEvent m_waiterLock = new AutoResetEvent(false); public void Enter() { // 指出这个线程想要获得锁 if (Interlocked....

2024-11-20 · 21 分钟 · SAM

第 29 章 基元线程同步构造

第 29 章 基元线程同步构造 本章内容 类库和线程安全 基元用户模式和内核模式构造 用户模式构造 内核模式构造 一个线程池线程阻塞时,线程池会创建额外的线程,而创建、销毁和调度线程所需的时间和内存资源是相当昂贵的。另外,许多开发人员看见自己程序的线程没有做任何有用的事情时,他们的习惯是创建更多的线程,寄希望于新线程能做有用的事情。为了构建可伸缩的、响应灵敏的应用程序,关键在于不要阻塞你拥有的线程,使它们能用于(和重用于)执行其他任务。第 27 章“计算限制的异步操作”讲述了如何利用线程执行计算限制的操作,第 28 章 “I/O 限制的异步操作” 则讲述了如何利用线程执行 I/O 限制的操作。 本章重点在于线程同步。多个线程同时访问共享数据时,线程同步能防止数据损坏。之所以要强调同时,是因为线程同步问题其实就是计时问题。如果一些数据由两个线程访问,但那些线程不可能同时接触到数据,就完全用不着线程同步。第 28 章展示了如何通过不同的线程来执行异步函数的不同部分。可能有两个不同的线程访问相同的变量和数据,但根据异步函数的实现方式,不可能有两个线程同时访问相同的数据。所以,在代码访问异步函数中包含的数据时不需要线程同步。 不需要线程同步是最理想的情况,因为线程同步存在许多问题。第一个问题是它比较繁琐,而且很容易写错。在你的代码中,必须标识出所有可能由多个线程同时访问的数据。然后,必须用额外的代码将这些代码包围起来,并获取和释放一个线程同步锁。锁的作用是确保一次只有一个线程访问资源。只要有一个代码块忘记用锁包围,数据就会损坏。另外,没有办法证明你已正确添加了所有锁定代码。只能运行应用程序,对它进行大量压力测试,并寄希望于没有什么地方出错。事实上,应该在 CPU (或 CPU 内核)数量尽可能多的机器上测试应用程序。因为 CPU 越多,两个或多个线程同时访问资源的机率越大,越容易检测到问题。 锁的第二个问题在于,它们会损害性能。获取和释放锁是需要时间的,因为要调用一些额外的方法,而且不同的 CPU 必须进行协调,以决定哪个线程先取得锁。让机器中的 CPU 以这种方式相互通信,会对性能造成影响。例如,假定使用以下代码将一个节点添加到链表头: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 // 这个类由 LinkedList 类使用 public class Node { internal Node m_next; // 其他成员未列出 } public sealed class LinkedList { private Node m_head; public void Add(Node newNode) { // 以下两行执行速度非常快的引用赋值 newNode....

2024-11-20 · 18 分钟 · SAM

第 28 章 I/O 限制的异步操作

第 28 章 I/O 限制的异步操作 本章内容: Windows 如何执行 I/O 操作 C# 的异步函数 编译器如何将异步函数转换成状态机 异步函数扩展性 异步函数和事件处理程序 FCL 的异步函数 异步函数和异常处理 异步函数和其他功能 应用程序及其线程处理模型 以异步方式实现服务器 取消 I/O 操作 有的 I/O 操作必须同步进行 I/O 请求优先级 第 27 章重点讲述了如何异步执行计算限制的操作,允许线程池在多个 CPU 内核上调度任务,使多个线程能并发工作,从而高效率地使用系统资源,同时提升应用程序的吞吐能力。本章重点讲述如何异步执行 I/O 限制的操作,允许将任务交由硬件设备处理,期间完全不占用线程和 CPU 资源。然而,线程池仍然扮演了一个重要的角色,因为如同你马上就要看到的那样,各种 I/O 操作的结果还是要由线程池线程来处理的。 28.1 Windows 如何执行 I/O 操作 首先讨论 Windows 如何执行同步 I/O 操作。图 28-1 是连接了几个硬件设备的计算机系统。每个硬件设备都有自己的电路板,每个电路板都集成了一个小型的、特殊用途的计算机,它知道如何控制自己的硬件设备。例如,硬盘驱动器就有一个小的电路板,它知道如何旋转碟片、寻道、在碟上读写数据以及和计算机内存交换数据。 图 28-1 Windows 如何执行执行同步 I/O 操作 程序通过构造一个 FileStream 对象来打开磁盘文件,然后调用 Read 方法从文件中读取数据。调用 FileStream 的 Read 方法时,你的线程从托管代码转变为本机/用户模式代码,Read 内部调用 Win32 ReadFile 函数(①)。ReadFile 分配一个小的数据结构,称为 I/O 请求包(I/O Request Packet, IRP)(②)。IRP 结构初始化后包含的内容有:文件句柄,文件中的偏移量(从这个位置开始读取字节),一个 Byte[] 数组的地址(数组用读取的字节来填充),要传输的字节数以及其他常规性内容。...

2024-11-20 · 18 分钟 · SAM

第 27 章 计算限制的异步操作

第 27 章 计算限制的异步操作 本章内容: CLR 线程池基础 执行简单的计算限制操作 执行上下文 协作式取消和超时 任务 Parallel 的静态 For,ForEach 和 Invoke方法 并行语言集成查询(PLINQ) 执行定时的计算限制操作 线程池如何管理线程 本章将讨论以异步方式操作的各种方式。异步的计算限制操作要用其他线程执行,例子包括编译代码、拼写检查、语法检测、电子表格重计算、音频或视频数据转码以及生成图像的缩略图。在金融和工程应用程序中,计算限制的操作也是十分普遍的。 大多数应用程序都不会花太多时间处理内存数据或执行计算。要验证这一点,可以打开“任务管理器”,选择“性能”标签。如果 CPU 利用率不到 100%(大多数时候都如此),就表明当前运行的进程没有使用由计算机的 CPU 内核提供的全部计算能力。CPU 利用率低于 100% 时,进程中的部分(但不是全部)线程根本没有运行。相反,这些线程正在等待某个输入或输出操作。例如,这些线程可能正在等待一个计时器到期①;等待在数据库/Web服务器/文件/网络/其他硬件设备中读取或写入数据;或者等待按键、鼠标移动或鼠标点击等。执行 I/O 限制的操作时,Microsoft Windows 设备驱动程序让硬件设备为你“干活儿”,但 CPU 本身“无所事事”。由于线程不在 CPU 上运行,所以“任务管理器”说 CPU 利用率很低。 ① 计时器“到期”(come due)的意思是还有多久触发它。 但是,即使 I/O 限制非常严重的应用程序也要对接收到的数据执行一些计算,而并行执行这些计算能显著提升应用程序的吞吐能力。本章首先介绍 CLR 的线程池,并解释了和它的工作和使用有关的一些基本概念。这些信息非常重要。为了设计和实现可伸缩的、响应灵敏和可靠的应用程序和组件,线程池是你必须采用的核心技术。然后,本章展示了通过线程池执行计算限制操作的各种机制。 27.1 CLR 线程池基础 如第 26 章所述,创建和销毁线程时一个昂贵的操作,要耗费大量时间。另外,太多的线程会浪费内存资源。由于操作系统必须调度可运行的线程并执行上下文切换,所以太多的线程还对性能不利。为了改善这个情况,CLR 包含了代码来管理它自己的线程池(thread pool)。线程池是你的应用程序能使用的线程集合。每 CLR 一个线程池;这个线程池由 CLR 控制的所有 AppDomain 共享。如果一个进程中加载了多个 CLR,那么每个 CLR 都有它自己的线程池。 CLR 初始化时,线程池中是没有线程的。在内部,线程池维护了一个操作请求队列。应用程序执行一个异步操作时,就调用某个方法,将一个记录项(entry)追加到线程池的队列中。线程池的代码从这个队列中提取记录项,将这个记录项派发(dispatch)给一个线程池线程。如果线程池中没有线程,就创建一个新线程。创建线程会造成一定的性能损失(前面已讨论过了)。然而,当线程池线程完成任务后,线程不会被销毁。相反,线程会返回线程池,在那里进入空闲状态,等待响应另一个请求。由于线程不销毁自身,所以不再产生额外的性能损失。 如果你的应用程序向线程池发出许多请求,线程池会尝试只用这一个线程来服务所有请求。然而,如果你的应用程序发出请求的速度超过了线程池线程处理它们的速度,就会创建额外的线程。最终,你的应用程序的所有请求都能由少量线程处理,所以线程池不必创建大量线程。 如果你的应用程序停止向线程池发出请求,池中会出现大量什么都不做的线程。这是对内存资源的浪费。所以,当一个线程池线程闲着没事儿一段时间之后(不同版本的 CLR 对这个时间的定义不同),线程会自己醒来终止自己以释放资源。线程终止自己会产生一定的性能损失。然而,线程终止自己是因为它闲的慌,表明应用程序本身就么有做太多的事情,所以这个性能损失关系不大。...

2024-11-20 · 20 分钟 · SAM

第 26 章 线程基础

第 26 章 线程基础 本章内容: Windows 为什么要支持线程 线程开销 停止疯狂 CPU 发展趋势 CLR 线程和 Windows 线程 使用专用线程执行异步的计算限制操作 使用线程的理由 线程调度和优先级 前台线程和后台线程 继续学习 本章将介绍线程的基本概念,帮助开发人员理解线程及其使用。我将解释 Microsoft Windows 为什么引入线程的概念、CPU 发展趋势、CLR 线程和 Windows 线程的关系、线程开销、Windows 如何调度线程以及公开了线程属性的 Microsoft .NET Framework 类。 本书第 V 部分“线程处理” 的各个章节将解释 Windows 和 CLR 如何协同提供一个线程处理架构。希望通过这些内容帮你打下一个良好的基础,学会高效使用线程来设计和构建响应灵敏的、可靠的、可伸缩的应用程序和组件。 26.1 Windows 为什么要支持线程 在计算机的早期岁月,操作系统没有线程的概念。事实上,整个系统只运行着一个执行线程,其中同时包含操作系统代码和应用程序代码。只用一个执行线程的问题在于,长时间运行的任务会阻止其他任务执行。例如,在 16 位 Windows 的那些日子,打印文档的应用程序很容易“冻结”整个机器,造成 OS (操作系统)和其他应用程序停止响应。有些应用程序的 bug 会造成死循环,同样会造成整个机器停止工作。 遇到这个问题,用户只好按 Reset 键或电源开关重启计算机。用户对此深恶痛绝(事实上,他们现在一样会),因为所有正在运行的应用程序都会终止。更重要的是,这些应用程序正在处理的数据都会无端地丢失。Microsoft 明白 16 位 Windows 不是理想的操作系统。随着计算机工业的持续进步,它不足以使 Microsoft 保持领先地位。所以,它们计划构建一个新的 OS 来满足企业和个人的需要。这个新的 OS 必须健壮、可靠、易于伸缩和安全,而且它必须弥补 16 位 Windows 的许多不足。新的 OS 内核最初通过 Microsoft Windows NT 发布。经过多年的发展,它已进行了大量改进,增加了大量功能。Microsoft 每次发布客户端和服务器 Windows 操作系统的最新版本时,都在其中采用了这个内核的最新版本。...

2024-11-20 · 8 分钟 · SAM

第 25 章 与 WinRT 组件互操作

第 25 章 与 WinRT 组件互操作 本章内容: CLR 投射与 WinRT 组件类型系统规则 框架投射 用 C# 定义 WinRT 组件 Windows 8/8.1 带来了一个新类库,应用程序可通过它访问操作系统功能。类库正式名称是 Windows 运行时(Windows Runtime, WinRT),其组件通过 WinRT 类型系统访问。首次发布时, WinRT 的许多目标都和 CLR 相同,例如简化应用程序开发,以及允许代码用不同编程语言实现以简化互操作。特别是,Microsoft 支持在原生 C/C++、JavaScript(通过 Microsoft 的 “Chakra” JavaScript 虚拟机)和 C#/Visual Basic(通过 CLR)中使用 WinRT 组件。 图 25-1 展示了 Windows 的 WinRT 组件所公开的功能,以及可以访问它们的 Microsoft 语言。对于原生 C/C++ 实现的应用程序,开发人员必须为每种 CPU 架构(x86,x64 和 ARM)单独编译代码。相比之下,.NET 开发人员只需编译一次(编译成 IL,CLR 自行将其编译成与主机 CPU 对应的本机代码)。JavaScript 应用程序则自带了源代码,“Chakra”虚拟机解析这些源代码,把它编译成与主机 CPU 对应的本机代码。其他公司也可制作能与 WinRT 组件互操作的语言和环境。 图 25-1 Windows 的 WinRT 组件所公开的功能,以及访问它们的各种语言...

2024-11-20 · 18 分钟 · SAM

第 24 章 运行时序列化

第 24 章 运行时序列化 本章内容 序列化/反序列化快速入门 使类型可序列化 控制序列化和反序列化 格式化器如何序列化类型实例 控制序列化/反序列化的数据 流上下文 将类型序列化为不同的类型以及将对象反序列化为不同的对象 序列化代理 反序列化对象时重写程序集和/或类型 序列化是将对象或对象图①转换成字节流的过程。反序列化是将字节流转换回对象图的过程。在对象和字节流之间转换是很有用的机制。下面是一些例子。 ① 本书将 object graph 翻译成“对象图”,对象图是一个抽象的概念,代表的是对象系统在特定时间点的一个视图。另一个常用的术语 object diagram 则是指总体 object graph 的一个子集。普通的对象模型(比如 UML 类图)描述的是对象之间的关系,而对象图侧重于它们的实例在特定时间点的状态。在面向对象应用程序中,相互关联的对象构成了一个复杂的网络。一个对象可能拥有或包含另一个对象,或者容纳了对另一个对象的引用。这样一来,不同的对象便相互链接起来了。这个对象网络便是对象图。它是一种比较抽象的结构,可在讨论应用程序的状态时使用它。注意,在 .NET Framework SDK 中文文档中,由对象相互连接而构成的对象图被称为“连接对象图形”。 ———— 译注 应用程序的状态(对象图)可轻松保存到磁盘文件或数据库中,并在应用层序下次运行时恢复。ASP.NET 就是利用序列化和反序列化来保存和还原会话状态的。 一组对象可轻松复制到系统的剪贴板,再粘贴回同一个或另一个应用程序,事实上, Windows 窗体和 Windows Presentation Foundation(WPF) 就利用了这个功能。 一组对象可克隆并放到一边作为“备份”;与此同时,用户操纵一组“主”对象。 一组对象可轻松地通过网络发送给另一台机器上运行的进程。Microsoft .NET Framework 的 Remoting(远程处理)架构会对按值封送(marshaled by value)的对象进行序列化和反序列化。这个技术还可跨 AppDomain 边界发送对象,具体如第 22 章“CLR 寄宿和 AppDomain”所述。 除了上述应用,一旦将对象序列化成内存中的字节流,就可方便地以一些更有用的方式处理数据,比如进行加密和压缩。 由于序列化如此有用,所以许多程序员耗费了大量时间写代码执行这些操作。历史上,这种代码很难编写,相当繁琐,还容易出错。开发人员需要克服的难题包括通信协议、客户端/服务器数据类型不匹配(比如低位优先/高位优先①问题)、错误处理、一个对象引用了其他对象、in 和 out 参数以及由结构构成的数组等。 ① little-endian/big-endian,也译成小段和大端。 ———— 译注 让人高兴的是,.NET Framework 内建了出色的序列化和反序列化的支持。上述所有难题都迎刃而解,而且.NET Framework 是在后台悄悄帮你解决的。开发者现在只需负责序列化之前和反序列化之后的对象处理,中间过程由 ....

2024-11-20 · 15 分钟 · SAM

第 23 章 程序集加载和反射

第 23 章 程序集加载和反射 本章内容 程序集加载 使用反射构建动态可扩展应用程序 反射的性能 设计支持加载项的应用程序 使用反射发现类型的成员 本章讨论了在编译时对一个类型一无所知的情况下,如何在运行时发现类型的信息、创建类型的实例以及访问类型的成员。可利用本章讲述的内容创建动态可扩展应用程序。在这种情况下,一般是由一家公司创建宿主应用程序,其他公司创建加载项(add-in)来扩展宿主应用程序。宿主不能基于一些具体的加载项来构建和测试,因为加载项由不同公司创建,而且极有可能是在宿主应用程序发布之后才创建的。这是宿主为什么要在运动时发现加载项的原因。 动态可扩展应用程序可利用第 22 章讲述的 CLR 寄宿和 AppDomain。宿主可以在一个 AppDomain 中运行加载项代码,这个 AppDomain 有它自己的安全性和配置设置。宿主还可通过卸载 AppDomain 来卸载加载项。在本章末尾,将花费一点时间来讨论如何将所有这些功能组合到一起————包括 CLR 寄宿、AppDomain、程序集加载、类型发现、实例实例构造和反射————从而构建健壮、安全而且可以动态扩展的应用程序。 重要提示 .NET Framework 4.5 引入了新的反射 API。旧的 API 缺点太多。例如,它对 LINQ 的支持不好,内建的策略对某些语言来说不正确,有时不必要地强制加载程序集,而且为很少遇到的问题提供了过于复杂的 API。新 API 解决了所有这些问题。但至少就 .NET 4.5 来说,新的反射 API 还不如旧 API 完整。利用新 API 和 System.Reflection.RuntimeReflcetionExtensions 类中的扩展方法,现在所有事情都可以做到。希望在 .NET Framework 未来的版本中为新 API 添加更多的方法。当然,对于桌面应用程序,旧 API 是仍然存在的,重新编译现有的代码不会出任何问题。但新 API 是未来的发展方向,这正是本章要全面讨论新 API 的原因。Windows Store 应用由于不用考虑向后兼容,所以必须使用新 API。 23.1 程序集加载 我们知道,JIT 编译器将方法的 IL 代码编译成本机代码时,会查看 IL 代码中引用了哪些类型。在运行时,JIT 编译器利用程序集的 TypeRef 和 AssemblyRef 元数据表来确定哪一个程序集定义了所引用的类型。在 AssemblyRef 元数据表的记录项中,包含了构成程序集强名称的各个部分。JIT 编译器尝试将与该标识匹配的程序集加载到 AppDomain 中(如果还没有加载的话)。如果被加载的程序集是弱命名的,那么标识中就只包含程序集的名称(不包含版本、语言文化及公钥标记信息)。①...

2024-11-20 · 17 分钟 · SAM

第 22 章 CLR 寄宿和 AppDomain

第 22 章 CLR 寄宿和 AppDomain 本章内容: CLR 寄宿 AppDomain 卸载 AppDomain 监视 AppDomain AppDomain FirstChance 异常通知 宿主如何使用 AppDomain 高级宿主控制 本章主要讨论两个主题:寄宿和 AppDomain。这两个主题充分演示了 Microsoft .NET Framework 的巨大价值。寄宿(hosting)使任何应用程序都能利用 CLR 的功能。特别要指出的是,它使现有的应用程序至少能部分使用托管代码编写。另外,寄宿还为应用程序至少能部分使用托管代码编写。另外,寄宿还为应用程序提供了通过编程来进行自定义和扩展的能力。 允许可扩展性意味着第三方代码可在你的进程中运行。在 Windows 中将第三方 DLL 加载到进程中意味着冒险。DLL 中的代码很容易破坏应用程序的数据结构和代码。DLL 还可能企图利用应用程序程序的安全上下文来访问它本来无权访问的资源。CLR 的 AppDomain 功能解决了所有这些问题。AppDomain 允许第三方的、不受信任的代码在现有的进程中运行,而 CLR 保证数据结构、代码和安全上下文不被滥用或破坏。 程序员经常将寄宿和 AppDomain 与程序集的加载和反射一起使用。这 4 种技术一起使用,使 CLR 成为一个功能极其丰富和强大的平台。本章重点在于寄宿和 AppDomain。下一章则会重点放在程序集加载和反射上。学习并理解了所有这些技术后,会发现今天在 .NET Framework 上面的投资,将来必会获得丰厚回报。 22.1 CLR 寄宿 .NET Framework 在 Windows 平台的顶部运行。这意味着 .NET Framework 必须用 Windows 能理解的技术来构建。首先,所有托管模块和程序集文件都必须使用 Windows PE 文件格式,而且要么是 Windows EXE 文件,要么是 DLL 文件。...

2024-11-20 · 15 分钟 · SAM