标签:hand 保护 ati border 参与 异常处理 word 强制 管理
1 clr寄宿-----.net framework在windows平台的顶部允许。者意味着.net framework必须用windows能理解的技术来构建。所有托管模块和程序集文件必须使用windows PE文件格式,而且要么是windows exe文件,要么是DLL文件
2,ICLRRuntimeHost可以做以下事情
①设置宿主管理器。该诉CLR宿主想参与与涉及以下操作的决策:内存分配、线程调度/同步以及程序集加载等。宿主还可声明它想获得有关垃圾回收启动和停止以及特定操作超时的通知
②获取CLR管理器。告诉CLR阻止使用某些类/成员。另外,宿主能分辨哪些代码可以调试,哪些不可以,以及当特定事件(例如AppDomain卸载、CLR停止或者堆栈移除异常)发生时宿主应调用哪个方法
③初始化并启动CLR
④加载程序集并执行其中的代码
⑤停止CLR,阻止任何更多的托管代码在Windows进程中运行
3,AppDomain
3,跨越AppDomain边界访问对象.
namespace ClrFromCSharp_2_2.LearnAppDomain { public class AppDomainRef { public static void Marshalling() { AppDomain adCallingTreadDomain = Thread.GetDomain();//获取当前线程运行的域 string callingDomainName = adCallingTreadDomain.FriendlyName; Console.WriteLine("Default AppDomain‘s friendly name={0}", callingDomainName); //获取并显示我们的AppDomain中包含了Main方法的程序集 string exeAssembly = Assembly.GetEntryAssembly().FullName; Console.WriteLine("Main assembly={0}", exeAssembly); //定义局部变量来引用一个AppDomain AppDomain ad2 = null; Console.WriteLine("\n Demo #1"); ad2 = AppDomain.CreateDomain("AD #2", null, null); MarshalByRefType mbrt = null; mbrt = (MarshalByRefType)ad2.CreateInstanceAndUnwrap(exeAssembly, "ClrFromCSharp_2_2.LearnAppDomain.MarshalByRefType");//利用AppDomain和程序集创建对象. Console.WriteLine("Type={0}", mbrt.GetType()); Console.WriteLine("Is proxy={0}", RemotingServices.IsTransparentProxy(mbrt));// //看起来我们像在MarshalByRefType上面调用一个方法,实则不然,我们在代理类型上调用一个方法,代理使线程切换到拥有对象的那个AppDomain,并在真实对象上调用 //真实的方法. mbrt.SomeMethod(); //卸载 AppDomain AppDomain.Unload(ad2); //mbrt 引用一个有效的代理对象,代理对象引用一个无效的AppDomain try { mbrt.SomeMethod(); Console.WriteLine("Successful"); } catch (AppDomainUnloadedException) { Console.WriteLine("Failed Call."); } //---Demo2---使用MarshalByValue进行跨AppDomain通信 Console.WriteLine("\n Demo #2"); ad2 = AppDomain.CreateDomain("AD #2", null, null); mbrt = (MarshalByRefType)ad2.CreateInstanceAndUnwrap(exeAssembly, "ClrFromCSharp_2_2.LearnAppDomain.MarshalByRefType");//利用AppDomain和程序集创建对象. MarshalByValType mbvt = mbrt.MethodWithReturn(); Console.WriteLine("Is proxy={0}", RemotingServices.IsTransparentProxy(mbvt));//证明得到的不是一个代理对象的引用 Console.WriteLine("Returned object created" + mbvt.ToString()); //卸载新的AppDomain AppDomain.Unload(ad2); //mbvt引用有效的对象:卸载AppDomain没用影响 try { Console.WriteLine("Returned object created" + mbvt.ToString()); Console.WriteLine("Successful"); } catch (AppDomainUnloadedException) { Console.WriteLine("Failed Call."); } //Demo3 :使用不可封送的对象,抛出异常 mbrt = (MarshalByRefType)ad2.CreateInstanceAndUnwrap(exeAssembly, "ClrFromCSharp_2_2.LearnAppDomain.MarshalByRefType");//利用AppDomain和程序集创建对象. NonMarshalableType nmt = mbrt.MethodArgAndReturn("abc"); //这里永远执行不到... } } public sealed class MarshalByRefType : MarshalByRefObject { public MarshalByRefType() { Console.WriteLine("{0} ctor running in {1}", this, GetType().ToString(), Thread.GetDomain().FriendlyName); } public void SomeMethod() { Console.WriteLine("Executing in" + Thread.GetDomain().FriendlyName); } public MarshalByValType MethodWithReturn() { Console.WriteLine("Executing in" + Thread.GetDomain().FriendlyName); return new MarshalByValType(); } public NonMarshalableType MethodArgAndReturn(string name) { Console.WriteLine("calling from {0} to {1}", name, Thread.GetDomain().FriendlyName); return new NonMarshalableType(); } } [Serializable] public sealed class MarshalByValType : Object { private DateTime m_creationTime = DateTime.Now; public MarshalByValType() { Console.WriteLine("{0} ctor running in {1},Created On {2:D}", this.GetType().ToString(), Thread.GetDomain().FriendlyName, m_creationTime); } public override string ToString() { return m_creationTime.ToLongDateString(); } } [Serializable] public sealed class NonMarshalableType : Object { public NonMarshalableType() { Console.WriteLine("Executing in" + Thread.GetDomain().FriendlyName); } } }
运行结果
Default AppDomain‘s friendly name=ClrFromCSharp_2_2.exe Main assembly=ClrFromCSharp_2_2, Version=1.0.0.0, Culture=neutral, PublicKeyToken=11fccde6e91ad1e9 Demo #1 ClrFromCSharp_2_2.LearnAppDomain.MarshalByRefType ctor running in ClrFromCSharp_2_2.LearnAppDomain.MarshalByRefType Type=ClrFromCSharp_2_2.LearnAppDomain.MarshalByRefType Is proxy=True Executing inAD #2 Failed Call. Demo #2 ClrFromCSharp_2_2.LearnAppDomain.MarshalByRefType ctor running in ClrFromCSharp_2_2.LearnAppDomain.MarshalByRefType Executing inAD #2 ClrFromCSharp_2_2.LearnAppDomain.MarshalByValType ctor running in AD #2,Created On 2020年2月13日 Is proxy=False Returned object created2020年2月13日 Returned object created2020年2月13日 Successful
1,线程也就是方法中,可以通过Thread.Get Domain(),来获取域的信息.也可以通过System.AppDomain.CurrentDomain获取
2,FriendName:一个用于辨识的名称.
3,Assembly.GetEntryAssembly().FullName获取当前运行程序的程序集的强名称(Full Name)
4,利用AppDomain.CreateDomain()创建AppDomain
当新建了一个App Domain后,其Loader堆是空的.CLr不在这个App Domain上创建任何线程,AppDomain中也不会运行代码.除非显式调用代码.
5,利用mbrt = (MarshalByRefType)ad2.CreateInstanceAndUnwrap(exeAssembly, "ClrFromCSharp_2_2.LearnAppDomain.MarshalByRefType");//利用AppDomain和程序集创建对象. ,注意,首先,利用该函数创建一个代理对象
两个参数.一个使程序集的FullName,一个是程序集所在的类的强名称.
mbrt = (MarshalByRefType)ad2.CreateInstanceAndUnwrap(typeof(MarshalByRefType).Assembly.FullName, typeof(MarshalByRefType).FullName);//利用AppDomain和程序集创建对象.
使用这个函数时候,线程切换到AppDomain ad2,然后在上面创建类型对象(派生自MarshalByRefObject),然后,返回给实际的ad1一个引用的代理对象:
该代理对象有完全一样的实列成员(属性,事件,方法)但是,其不含实列的字段.相反,其含有
通过堆栈调式和Porxy代理方法可以知道,这是一个代理对象.当执行该代理对象的方法时,实际上线程切换到了ad2,并且在ad2上执行方法.
执行完毕后,其返回到原来的App Domain之中.
6,接下来,卸载了AppDomain.包括了所有程序集.并且强制执行一次垃圾回收.下一次调用实际上是调用代理上面的方法,代理发现方法的真实对象所在的APp已经卸载,抛出错误AppDomainUnloadedException异常.
7,对于派生自MarshalByRefObject派生的类的字段访问时,实际上调用System.Object的Field Getter或FieldSetter方法(利用反射)获取或者设定字段值.因此,访问字段性能很差.
8,
生存期租约.由于第二个AppDomain中的对象没有根,所以使用代理引用原始对象可以被垃圾回收.重写InitializeLifetimeService
public class MyClass : MarshalByRefObject { [SecurityPermissionAttribute(SecurityAction.Demand, Flags=SecurityPermissionFlag.Infrastructure)] public override Object InitializeLifetimeService() { ILease lease = (ILease)base.InitializeLifetimeService(); if (lease.CurrentState == LeaseState.Initial) { lease.InitialLeaseTime = TimeSpan.FromMinutes(1); lease.SponsorshipTimeout = TimeSpan.FromMinutes(2); lease.RenewOnCallTime = TimeSpan.FromSeconds(2); } return lease; } }
9,按值封送对象([serialzible],但是未实现MarshalByRefObject:
当一个对象被标识成[Serialable]时候,CLR将对象实列的字段序列化为一个字节数组,然后,CLR在目标的APPDOMAIN中反序列化对象,并且强制加载目标对象的程序集.也就是在目标AppDomain中精确复制了源对象.
10,当上述两种方法都不行时,则报错.
11,卸载AppDomain.
使用AppDomain.unload()来卸载AppDomain.
12,监视AppDomain
public sealed class AppDomainMonitorDelta:IDisposable { private AppDomain m_appDomain; private TimeSpan m_thisADCpu; private Int64 m_thisADMemoryInUse; private Int64 m_thisADMemoryAllocated; static AppDomainMonitorDelta() { AppDomain.MonitoringIsEnabled = true; } public AppDomainMonitorDelta(AppDomain ad) { m_appDomain = ad ?? AppDomain.CurrentDomain; m_thisADCpu = m_appDomain.MonitoringTotalProcessorTime; m_thisADMemoryInUse = m_appDomain.MonitoringSurvivedMemorySize; m_thisADMemoryAllocated = m_appDomain.MonitoringTotalAllocatedMemorySize; } public void Dispose() { GC.Collect(); Console.WriteLine("FriendlyName={0},cpu={1}ms", m_appDomain.FriendlyName, (m_appDomain.MonitoringTotalProcessorTime - m_thisADCpu).TotalMilliseconds); Console.WriteLine("Allocated {0:N0} bytes of which {1:N0} survived GCS", m_appDomain.MonitoringTotalAllocatedMemorySize - m_thisADMemoryAllocated, m_appDomain.MonitoringSurvivedMemorySize - m_thisADMemoryInUse); } }
该类用于监视两个时间点之间AppDomain发生的变化
using(new AppDomainMonitorDelta(null)) { var list = new List<object>(); for (var x = 0; x < 2000; x++) { list.Add(new byte[10000]); } for (var x = 0; x < 2000; x++) { new Byte[10000].GetType(); } Int64 stop = Environment.TickCount + 5000; while (Environment.TickCount < stop) ; }
13,AppDomain FirstChanceException 异常通知---
public class TestAppDomainFirstChanceNotify:MarshalByRefObject//创建一个引用传递的对象. { private string m_name; static TestAppDomainFirstChanceNotify()//在类初始化的时候,添加了当appdomain发生异常时,FirstChanceException添加事件. { Thread.GetDomain().FirstChanceException += (obj, e) => { Console.WriteLine("FirstChanceCaused in {0}", Thread.GetDomain().FriendlyName); }; } public TestAppDomainFirstChanceNotify() : this("notify") { } public TestAppDomainFirstChanceNotify(string name) { m_name = name; Console.WriteLine("created at appdomain {0}", Thread.GetDomain().FriendlyName);//创建对象. } public void PullException(string message)//调用方法,抛出异常. { Console.WriteLine("try throw Exception at appdomain {0}", Thread.GetDomain().FriendlyName); throw new Exception(message); } }
结果:
public static void CallFirstChance() { Thread.GetDomain().FirstChanceException += FirstChangeHandler;//当当前appdomain发生第一次异常的时候,调用回调函数. AppDomain ad = AppDomain.CreateDomain("AD0");//创建新的app domain---ad; TestAppDomainFirstChanceNotify t = (TestAppDomainFirstChanceNotify)ad.CreateInstanceAndUnwrap(typeof(TestAppDomainFirstChanceNotify).Assembly.FullName, typeof(TestAppDomainFirstChanceNotify).FullName); try//创建代理对象 { t.PullException("pull exception");//代理对象调用异常方法. } catch(Exception e) { Console.WriteLine("exception happened at {0}", Thread.GetDomain().FriendlyName); } }
created at appdomain AD0:创建对象
try throw Exception at appdomain AD0://抛出异常
FirstChanceCaused in AD0//调用ad0 中的FirstChanceException事件.
pull exception//调用当前app中的FirstChanceCaused
exception happened at ClrFromCSharp_2_2.exe//catch吃掉异常.
clr via c# clr寄宿和AppDomain (一)
标签:hand 保护 ati border 参与 异常处理 word 强制 管理
原文地址:https://www.cnblogs.com/frogkiller/p/12304609.html