第 22 章 CLR 寄宿和 AppDomain
- AppDomain是一组程序集的
容器
- 一个AppDomain的代码不能直接访问另一个AppDomain创建的对象,如果要访问,只能通过
按引用封送
或按值封送
- AppDomain可以卸载,但是不支持AppDomain卸载某个程序集
- AppDomain 可以单独保护 AppDomain 创建后应用一个权限集
- AppDomain 创建后会关联一组配置设置。这些设置主要影响 CLR 在 AppDomain 中加载程序集的方式。涉及搜索路径、版本绑定重定向、卷影复制以及加载器优化
跨越 AppDomain 边界访问对象
- 派生自
System.MarshalByRefObject
按引用封送,可以通过CreateInstanceAndUnwrap
将一个AppDomain中的对象按引用
封送到另一个AppDomain中,并返回对象的代理对象
,但是性能很差。 - 但是如果没有派生自
System.MarshalByRefObject
那么将无法按引用封送,如果对象可序列化,那么可以采用按值封送
,CLR将对象实例化序列化
成字节数组
然后从源AppDomain复制到目标AppDomain后反序列化
并将反序列化对象的程序集加载到目标AppDomain,实例化出对象,然后赋值。原文写的是精准复制
预留位置
卸载AppDomain
AppDomain.Unload
会阻塞调用线程
监视 AppDomain
- 下面是一个书上的工具类
private sealed class AppDomainMonitorDelta : IDisposable {
private AppDomain m_appDomain;
private TimeSpan m_thisADCpu;
private Int64 m_thisADMemoryInUse;
private Int64 m_thisADMemoryAllocated;
static AppDomainMonitorDelta() {
// 确定已打开了 AppDomain 监视
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异常处理
标记一下,用到再看