应用程序域 koma

   AppDomain是一组程序集的逻辑容器, AppDomain唯一的作用就是进行隔离, 是.Net中独有的. 创建一个托管应用程序同时会创建一个默认AppDomain

  AppDomain具体功能

    1.一个AppDomain中的代码创建的对象不能由另一个AppDomain中的代码直接访问

        如果需要访问,则需要通过代理的形式, 即使用"按引用封发" 和"按值封发"

    2.  AppDomain可以卸载

           CLR不支持从一个AppDomain卸载程序集,但是可以卸载AppDomain, 卸载AppDomain的同时,AppDomain中分配的所有资源一并释放

    3.  AppDomain可以单独保护

        创建AppDomain的同时,可以分配一个权限

    4.. AppDomain可以单独配置

        在创建AppDomain的同时,亦可以独立设置配置

   创建AppDomain

//参数说明: 1: 应用程序域名  2: 权限  3:配置   传null则表示按当前AppDomain配置
AppDomain appDomain = AppDomain.CreateDomain("应用程序域名", null, null);

  跨AppDomain访问对象

    跨AppDomain访问对象有3种行为,  "按引用封送" , "按值封送", "不能封送"

      首先构造3个类,即按 " 按应用封送" , "按值封送", "不能封送" ,注意, 如何封送,或者说能不能封送, 是有这个类型自己决定的

//按应用封送
publicclass MarshlaByRefType : MarshalByRefObject
{
publicvoid DoSomthing()
{
//.....
}
}

//按值封送
[Serializable]
publicclass MarshalByValType : Object
{
publicvoid DoSomthing()
{
//.....
}
}

//不能封送
publicclass NonMarshalableType : Object
{
publicvoid DoSomthing()
{
//.....
}
}

 调用:

//通过线程,可以获取当前AppDomain
AppDomain currAppDomain = System.Threading.Thread.GetDomain();
//输出当前AppDomain 名称,FriendlyName 是只读的,只有创建是才可以赋值, 默认AppDomain名称为应用程序名
Console.WriteLine(currAppDomain.FriendlyName);

//获取当前程序集名称
string exeAssemble = Assembly.GetEntryAssembly().FullName;

按引用封送

//按应用封送
AppDomain refAppDomain = AppDomain.CreateDomain("RefAddDomain", null, null);
MarshalByRefType marshalRefType
= (MarshalByRefType)refAppDomain.CreateInstanceAndUnwrap(exeAssemble, "MarshalByRefType");
/*
* 顺利执行
* 当代码执行到此处时, 线程会切换到refAppDomain的应用程序与中,执行真实的DoSomthring()
* 此处的refAppDomain 只不过是一个代理引用
*/
marshalRefType.DoSomthing();
//调用IsTransparentProxy判断是否为代理 Result: true
Console.WriteLine("Is Proxy={0}", RemotingServices.IsTransparentProxy(refAppDomain));

按值封送

//按值封送
AppDomain valAppDomain = AppDomain.CreateDomain("RefAddDomain", null, null);
MarshalByValType marshalValType
= (MarshalByValType)valAppDomain.CreateInstanceAndUnwrap(exeAssemble, "MarshalByValType");
/*
* 顺利执行
* 代码执行到此处时,实际调用的是当前AppDomain marshalValType的DoSomthing()方法
* 因为MarshalByValType标记了Serializable特性
*/
marshalRefType.DoSomthing();
//调用IsTransparentProxy判断是否为代理 Result: false
Console.WriteLine("Is Proxy={0}", RemotingServices.IsTransparentProxy(marshalValType));

不能封送

//不能封送
AppDomain nonAppDomain = AppDomain.CreateDomain("RefAddDomain", null, null);
NonMarshalableType marshalNonType
= (NonMarshalableType)nonAppDomain.CreateInstanceAndUnwrap(exeAssemble, "NonMarshalableType");
/*
* 此处异常
*/
marshalRefType.DoSomthing();

监视AppDomain
  设置AppDomain的MonitoringEnabled属性为true, 启用监视.  设置为true后,无法设置为false,即启用监视后不能关闭

  启用监视后, 可以通过下面四个只读属性查看AppDomain运行相关参数

            AppDomain.MonitoringIsEnabled =true;
//所有AppDomain使用字节数
AppDomain.MonitoringSurvivedProcessMemorySize;
//当前正在使用的字节数
nonAppDomain.MonitoringSurvivedMemorySize;
//此AppDomain分配的直接数
nonAppDomain.MonitoringTotalAllocatedMemorySize;
//CPU占用率
nonAppDomain.MonitoringTotalProcessorTime;

AppDomain FirstChance 异常通知

  通过设置FirstChanceException事件 ,可以获取AppDomain异常,但是无法终止,  当AppDomain遇到异常时,会向上查找Catch快,如果没有找到,则会继续向上抛,知道遇到捕获快为止,反之程序异常终止

   注意:

    不同的AppDomain引用System.dll时, 每个AppDomain都会创建的自己的内存区域,也就是说AppDomain之见毫不相干,各干各得, 虽然这是一种浪费,但是为了保证隔离性,这是必须的,   同时卸载AppDomain时,也不会影响其他AppDomain.

原文地址:https://www.cnblogs.com/yihui/p/2392643.html