目录

一、进程的概念与作用

二、应用程序域

三、深入了解.NET上下文

四、进程应用程序域与线程的关系

 

三、深入了解.NET上下文

3.1 .NET上下文的概念

应用程序域是进程中承载程序集的逻辑分区,在应用程序域当中,存在更细粒度的用于承载.NET对象的实体,那就.NET上下文Context。
所有的.NET对象都存在于上下文当中,每个AppDomain当中至少存在一个默认上下文(context 0)。
一般不需要指定特定上下文的对象被称为上下文灵活对象(context-agile),建立此对象不需要特定的操作,只需要由CLR自行管理,一般这些对象都会被建立在默认上下文当中。

 

图3.0

3.2 透明代理

在上下文的接口当中存在着一个消息接收器负责检测拦截和处理信息,当对象是MarshalByRefObject的子类的时候,CLR将会建立透明代理,实现对象与消息之间的转换。
应 用程序域是CLR中资源的边界,一般情况下,应用程序域中的对象不能被外界的对象所访问。而MarshalByRefObject 的功能就是允许在支持远程处理的应用程序中跨应用程序域边界访问对象,在使用.NET Remoting远程对象开发时经常使用到的一个父类。
此文章针对的是进程与应用程序域的作用,关于MarshalByRefObject的使用已经超越了本文的范围,关于.NET Remoting 远程对象开发可参考:“回顾.NET Remoting分布式开发”

 

3.3 上下文绑定

当系统需要对象使用消息接收器机制的时候,即可使用ContextBoundObject类。ContextBoundObject继承了MarshalByRefObject类,保证了它的子类都会通过透明代理被访问。
在 第一节介绍过:一般类所建立的对象为上下文灵活对象(context-agile),它们都由CLR自动管理,可存在于任意的上下文当中。而 ContextBoundObject 的子类所建立的对象只能在建立它的对应上下文中正常运行,此状态被称为上下文绑定。其他对象想要访问ContextBoundObject 的子类对象时,都只能通过代透明理来操作。

下面的例子,是上下文绑定对象与上下文灵活对象的一个对比。Example 是一个普通类,它的对象会运行在默认上下文当中。而ContextBound类继承了ContextBoundObject,它的对象是一个上下文绑定对 象。ContextBound还有一个Synchronization特性,此特性会保证ContextBound对象被加载到一个线程安全的上下文当中 运行。另外,Context类存在ContextProperties属性,通过此属性可以获取该上下文的已有信息。

 1     class Program
 2     {
 3         public class Example
 4         {
 5             public void Test()
 6             {
 7                 ContextMessage("Example Test\n");
 8             }
 9             //访问上下文绑定对象测试
10 public void Sync(ContextBound contextBound) 11 { 12 contextBound.Test("Example call on contextBound\n"); 13 } 14 } 15 16 [Synchronization] 17 public class ContextBound:ContextBoundObject 18 { 19 public void Test(string message) 20 { 21 ContextMessage(message); 22 } 23 } 24 25 static void Main(string[] args) 26 { 27 Example example = new Example(); 28 example.Test(); 29 ContextBound contextBound = new ContextBound(); 30 contextBound.Test("ContentBound Test\n"); 31 example.Sync(contextBound); 32 Console.ReadKey(); 33 } 34 35 //显示上下文信息
36 public static void ContextMessage(string data) 37 { 38 Context context = Thread.CurrentContext; 39 Console.WriteLine(string.Format("{0}ContextId is {1}", data, context.ContextID)); 40 foreach (var prop in context.ContextProperties) 41 Console.WriteLine(prop.Name); 42 Console.WriteLine(); 43 } 44 }

运行结果

由运行结果可以发现,example对象一般只会工作于默认上下文context 0 当中,而contextBound则会工作于线程安全的上下文 context 1当中。当example需要调用contextBound对象时,就会通过透明代理把消息直接传递到context 1中。