应用程序域进一步认识
新知识点:
- 一个AppDomain中创建的对象不能由另一个AppDomain的代码进行访问,必须进行特殊的声明,使用特殊的跨域调用;
- AppDomain 可以单独配置;
- 每个AppDomain都有自己的Loader堆,记录自AppDomain创建以来,访问过哪些类型,每个类型对象都有一个方法表,指向JIT编译的本地代码;
运行示例:
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading; using System.Reflection; using System.Runtime.Remoting; namespace FactoryMode { [Serializable] public class Program : MarshalByRefObject { //在调用此方法时,观察"调用堆栈",发现一次"外部代码"的切换,表明自进行了一次跨域操作 public void NotMainMethod() { //AppDomain.CurrentDomain 可以得到同样的结果 var curCallingDomain = Thread.GetDomain(); var curCallingDomainName = curCallingDomain.FriendlyName; Console.WriteLine("Cross-domain calling, curdomain name={0}.", curCallingDomainName); } static void Main(string[] args) { var curCallingDomain = Thread.GetDomain(); var curCallingDomainName = curCallingDomain.FriendlyName; Console.WriteLine("Default AppDomain's friendly name={0}.", curCallingDomainName); string exeAssembly = Assembly.GetExecutingAssembly().CodeBase; Console.WriteLine("Main assembly={0}.", exeAssembly); AppDomain otherDomain = null; Console.WriteLine("{0}Demo #1", Environment.NewLine); otherDomain = AppDomain.CreateDomain("AD #2", null, null); //在"AD#2"应用程序域中创建 Programs 对象,并向默认应用程序域返回它的引用; var mbrt = (Program)otherDomain.CreateInstanceFromAndUnwrap(exeAssembly, "FactoryMode.Program"); Console.WriteLine("Type={0}", mbrt.GetType()); Console.WriteLine("Is proxy={0}", RemotingServices.IsTransparentProxy(mbrt)); //利用引用调用方法,方法中的打印显示出此时线程正运行在"AD#2"应用程序域中 mbrt.NotMainMethod(); Console.Read(); } } }
- 进行跨域封送,必须支持序列化;
- 例子展示了跨域的引用传递,另外还有值传递;
- AppDomain 的构造 AppDomainSetup 参数决定了是否使用单独的配置;
备注:
- 获取程序集的路径名,是用 CodeBase 字段 - -;
- 要获得主程序集引用的其他程序集,可以通过对统一路径下dll的加载来完成,并不需要反射什么的其他手段;
卸载AppDomain:
- 挂机进程中执行过托管代码的所有线程;
- 检查正在该AppDomain上运行的线程,与会返还到该AppDomain上运行的线程;
- 抛出 ThreadAbortException,执行所有 finally 块中的内容进行资源清理;
- 在公共堆中遍历已卸载AppDomain中的对象,进行标记后进行垃圾回收;
- 恢复剩余所有线程的执行;
监视AppDomain:
非常好用的功能,可以用来做资源监控,性能监测;
- MonitoringSurvivedProcessMemorySize: 静态属性,当前 CLR 控制的所有 AppDomain 正在使用的字节数;
- MonitoringTotalAllocatedMemorySize: 实例属性,返回特定的 AppDomain 已分配的字节数;
- MonitoringSurvivedMemorySize: 实例属性,返回特定的 AppDomain 正在使用的字节数;
- MonitoringTotalProcessorTime: 实例属性,返还特定的 AppDomain 的CPU占用率;