应用程序域进一步认识

新知识点:

  • 一个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占用率;

 

posted on 2016-11-06 11:25  青墨淡潋  阅读(134)  评论(0编辑  收藏  举报