.Net下的AppDomain编程

c#动态加载卸载DLL的方法 c#中通过反射可以方便的动态加载dll程序集,但是如果你需要对dll进行更新,却发现.net类库没有提供卸载dll程序集的方法。在.net 中,加入了应用程序域的概念,应用程序域是可以卸载的。也就是说,如果需要对动态加载的dll程序集进行更新,可以通过以下方法解决: 新建一个应用程序域,在该应用程序域中动态加载DLL,然后可以卸载掉该应用程序域。该应用程序域被卸载的时候,相关资源也会被回收。 要想这样实现,就要让你程序的currentDomain和新建的newDomain之间进行通信,穿过应用程序域的边界。从网上找到了某大牛的解决方法,抄下来留给自己看吧: 代码如下:using Syst 立即下载
 

    最近在对AppDomain编程时遇到了一个问题,卸载AppDomain后,在内存中还保留它加载的DLL的数据,所以即使卸载掉AppDomain,还是无法更新它加载的DLL.看来只有关闭整个进程来更新DLL了.

--------------------------------------------------------------------------------------------------------------

    我们知道,进程是操作系统用于隔离众多正在运行的应用程序的机制。在.Net之前,每一个应用程序被加载到单独的进程中,并为该进程指定私有的虚拟内存。进程不能直接访问物理内存,操作系统通过其它的处理把这些虚拟内存映射到物理内存或IO设备的某个区域,而这些物理内存之间不会有重叠,这就决定了一个进程不可能访问分配给另一个进程的内存。相应地,运行在该进程中的应用程序也不可能写入另一个应用程序的内存,这确保了任何执行出错的代码不会损害其地址空间以外的应用程序。在这种机制下,进程作为应用程序之间一个独立而安全的边界在很大程度上提高了运行安全。

进程的缺点是降低了性能。许多一起工作的进程需要相互通信,而进程却不能共享任何内存,你不能通过任何有意义的方式使用从一个进程传递到另一个进程的内存指针。此外,你不能在两个进程间进行直接调用。你必须代之以使用代理,它提供一定程度的间接性。虽然,使用动态连接库dll让所有的组件运行在同一空间,一定程度上可以提高性能,但这些组件相互影响,一个组件的错误将极有可能导致整个应用程序的崩溃,“dll地狱”更是让许多应用程序难以避免。

应用程序域(AppDomain)


在.Net中,应用程序有了一个新的边界:应用程序域(以下简称域)。它是一个用于隔离应用程序的虚拟边界。为了禁止不应交互的代码进行交互,这种隔离是必要的。.Net的应用程序在域层次上进行隔离,一个域中的应用程序不能直接访问另一个域中的代码和数据。这种隔离使得在一个应用程序范围内创建的所有对象都在一个域内创建,确保在同一进程中一个域内运行的代码不会影响其他域内的应用程序,大大提高了运行的安全。

.Net结构中,由于公共语言运行库能够验证代码是否为类型安全的代码,所以它可以提供与进程边界一样大的隔离级别,其性能开销也要低得多。你可以在单个进程中运行几个域,而不会造成进程间调用或切换等方面的额外开销。这种方法是把任何一个进程分解到多个域中,允许多个应用程序在同一进程中运行,每个域大致对应一个应用程序,运行的每个线程都在一个特殊的域中。如果不同的可执行文件都运行在同一个进程空间中,它们就能轻松地共享数据或直接访问彼此的数据。这种代码同运行同一个进程但域不同的类型安全代码一起运行时是安全的。在一个进程内运行多个应用程序的能力显著增强了服务器的可伸缩性。

域间通信


域是.Net 带来的一个重要改进,它不仅将众多在运行的应用程序隔离开来,还不影响彼此间通信。虽然,公共语言运行库禁止在不同域中的对象之间进行直接调用,但我们可以复制这些对象,或通过代理访问这些对象。如果以前一种方式,那么对该对象的调用为本地调用。也就是说,调用方和被引用的对象位于同一域中。如果通过代理访问对象,调用方和被引用的对象位于不同的域中,对该对象的调用被视为远程调用,这种情形与两个进程间的调用或两台计算机间的调用结构大致相同。这时,需要被引用对象的元数据对于两个域均可用,以便.Net即时编译JIT能正确执行。

域与线程的关系


在.Net中,线程是公共语言运行库用来执行代码的操作系统构造。在运行时,所有托管代码均加载到一个域中,由特定的操作系统线程来运行。然而,域和线程之间并不具有一一对应关系。在任意给定时间,单个域中可以执行不止一个线程,而且特定线程也并不局限在单个域内。也就是说,线程可以跨越域边界,不为每个域创建新线程。当然,在指定时刻,每一线程都只能在一个域中执行。运行库会跟踪所有域中有哪些线程正在运行。通过调用.Net类库的 Thread.GetDomain 方法,你还可以确定正在执行的线程所在的域。

域的创建


作为公共语言运行库的隔离单元,域在进程中创建和运行。.Net结构中,运行时宿主(也叫作运行时主机)是负责将运行时载入进程并在域中执行用户代码和托管代码的应用程序。运行时宿主包括ASP.Net、浏览器Internet Explorer 和 Windows等外壳程序,负责创建进程和默认域,例如,Asp.Net为每个运行在web服务器上的web应用程序创建一个域。浏览器Internet explore创建运行受管制控件的域。

对多数应用程序,你并不必须创建相应的域,每次CLR在初始化一个进程时,将创建默认域,并使该进程运行于这个默认域下。然而,默认域不能由任何系统调用来卸载,该域只有在进程被卸载之后才能被销毁。如果直接在默认域下编程或运行代码,而由于某种原因域的代码崩溃了,那么就有使得整个服务随之崩溃的风险。

于是,针对不同的应用程序,应该创建和配置相应的域并载入适当的程序集。.Net为此提供了丰富的类库。其中,AppDomain 类是域的编程接口,其大量的(重载)方法能完成以下任务:

· 创建域

· 在域中加载程序集和类型

· 枚举域中的程序集和线程

· 卸载域

创建新域时,使用AppDomain 类的静态方法CreateDomain。你可以为域命名并按该名称来引用域。下面的示例语句创建新域,并为它指定名称 MyDomain:

AppDomain myDomain = AppDomain.CreateDomain("MyDomain");


然后你可以查询当前域的名称和新创建子域的名称:

string hostDomain=AppDomain.CurrentDomain.FriendlyName;
          string childDomain=myDomain.FriendlyName;


在这里,属性FriendlyName表示的是域的友好名称,友好名称通过从程序集的基本代码中去除目录路径而形成。例如,文件名为 "d:/MyAppDomain/MyAssembly.exe" 的程序集加载到默认域中,域的友好名称就是 "MyAssembly.exe"。

更一般的是,在创建域之前,先设置好域的参数,这可以通过类AppDomainSetup来完成。该类的ApplicationBase 属性定义应用程序的根目录, AppDomainSetup 类还有一个极重要的属性变量LoaderOptimizzation,取值可以是MultiDomain,MultiDomainHost和SignleDomain等,用以指定被加载程序集的类别(共享程序集或域专用程序集),例如,以下语句把程序集设置为域专用程序集:

appDomainSetup.LoaderOptimization=LoaderOptimizatiion.SigleDomain;


对以上两个方面简单归纳一下,对域的典型操作就包括:设置参数然后创建两个步骤,语句示例如下:

AppDomainSetup appDomainSetup=new AppDomainSetup();//实例化域设置
appDomainSetup.LoaderOptimization=LoaderOptimization.SingleDomain; //指定域类别
AppDoman ad=AppDomain.CreateDomain(domainName,appDomainSetup); //创建域
...
//应用程序在这里运行代码
...
AppDomain.Unload(ad);//卸载域


卸载域



当使用完域时,可使用AppDomain类Unload()静态方法将其卸载。要卸载进程中在运行的托管代码,只能卸载代码运行时所在的域而不能卸载单独的程序集或类型,Unload方法会正常关闭指定的域。这时,载入域的所有程序集都会被移除,并且无法再使用。不过,如果域中的程序集对域是非特定的(域无关程序集,也即共享程序集),则程序集的数据会保留在内存中,直到整个进程关闭。除了关闭整个进程,没有机制可以卸载非特定于域的程序集。在某些情况下,卸载应用程序域的请求不起作用,并导致 CannotUnloadAppDomainException。由于一个进程中允许包含多个域,某个域可以在不停止整个进程的情况下卸载。以这样的方式卸载不再需要的代码,可以减少内存占用并极大提高应用程序的可缩放性。此外,由于线程并不与域一一对应,当域中存在活动线程时,调用AppDomain.Unload方法可能无法将域卸载并导致异常。

另外,ICorRuntimeHost 接口包括一个名为 Stop 的方法,宿主可以使用该方法从进程中强制卸载运行库。当调用 Stop 时,将立即卸载所有域(包括默认域和所有非特定于域的代码),并从进程中全部移除运行库。当对进程调用 Stop 后,不能将运行库加载回该进程。要再次开始运行托管代码,必须创建一个新的进程。


在域中加载程序集


从上面的论述不难看出:要运行应用程序,必须首先将程序集(.Net下经编译产生,包含IL中间语言、元数据及清单等)加载到域中。而且一个域中可装载多个程序集。默认情况下,公共语言运行库自动将一个程序集加载到包含引用该程序集的代码的域。通过此方法,该程序集的代码和数据独立于使用该程序集的应用程序。

自行创建域的好处之一便是可以指定如何装载程序集。在域中有以下两种方式加载程序集:

1、将当前程序集加载入单独的域中,同一个程序集可能有多个副本;

2、以非特定于域的形式加载程序集,让一个程序集在多个域间共享;

这两种方式各自偏重于安全性和性能,需要视具体情况在二者之间权衡。具体地,在 .Net 框架中,System.Reflection.Assembly 类提供以下静态方法将程序集加载至域:

· Load()在给顶程序集名称的前提下,加载该程序集:

Assembly SampleAssembly;
…
SampleAssembly = Assembly.Load("System.Data");//根据类型加载程序集


· LoadFrom()在已知程序集文件名或路径等信息的情况下加载程序集:

Assembly SampleAssembly;
…
SampleAssembly = Assembly.LoadFrom("c://Sample.Assembly.dll");//根据已有程序集名称加载


参考资料:

《Microsoft .NET Framework程序设计》《.NET Framework高级编程》《.NET框架精髓 》等
使用PLINK做GWAS(2) 利用PLINK对单基因控制的性状进行定位,之前一篇文章粗滤的记录了一下使用PLINK的命令,本次博客主要记录一下如何根据SNP芯片的数据制作PLINK的格式,以及分析的步骤,最后数据的可视化。 首先,有的公司给的新片的数据就是一个excel表格,列表示的是样品,行表示的是基因型,基因型用ATCG构成,当然有的基因型是用数字0或者1表示的。下面我拿到的一个数据是15个样品构成的基因型,有13个样品是突变体,2个样品是野生型。 格式如下: 第二步:将此基因型存成csv文件,使用R进行读取,在R中制作pl 阅读详情

相关推荐

告别昂贵硬件!用Unity3D 2023 + ROS2 Humble搭建你的第一个SLAM仿真实验室(保姆级教程)

本文提供了一份详细的教程,介绍如何使用Unity3D 2023和ROS2 Humble搭建SLAM仿真实验室,无需昂贵硬件即可实现虚拟传感器模拟和算法测试。通过Docker容器配置、ROS2安装优化及Unity插件集成,开发者可以快速构建高精度的仿真环境,适用于自主导航、多传感器标定等场景。

weixin_42526353的博客 434

C# DLL 注入 (转)

C#中的DLL注入

jiangxinyu的专栏 6081

期末求生指南:手把手教你用浏览器开发者工具绕过百一测评切屏检测

本文详细介绍了如何利用浏览器开发者工具绕过百一测评的切屏检测功能。通过分析JavaScript事件监听机制,定位关键检测代码,并提供实时调试和本地覆盖两种修改方法,帮助学生在遵守规则的前提下更灵活地应对在线考试。文章还包含风险控制和替代方案等实用建议。

weixin_28698059的博客 550

浅析.Net下的AppDomain编程

我们知道,进程是操作系统用于隔离众多正在运行的应用程序的机制。在.Net之前,每一个应用程序被加载到单独的进程中,并为该进程指定私有的虚拟内存。进程不能直接访问物理内存,操作系统通过其它的处理把这些虚拟内存映射到物理内存或IO设备的某个区域,而这些物理内存之间不会有重叠,这就决定了一个进程不可能访问分配给另一个进程的内存。相应地,运行在该进程中的应用程序也不可能写入另一个应用程序的内存,这确保了任

Ninth(天下第九)的专栏 1449

OPC DCOM详细配置方法 - 不关防火墙不换登陆用户

1. 前言   OPC DCOM的设置是实现跨网络OPC通信的基础,现有的一些OPC DCOM配置教程虽然讲解了如何配置DCOM,但没有讲清楚为什么要这么做,而且各个教程涉及的配置方法也不尽相同。   为了彻底搞清楚OPC DCOM的配置过程,我重新做了两台机器的系统,一台是Windows 7 32位,一台是Windows 10 64位,并且重零开始完整的测试了正常运行OPC DCOM所需的最少的...

steventian72的博客 3万+

科研党必备:用Python+Excel批量下载文献的保姆级教程(附常见错误解决)

本文提供了一套利用Python和Excel实现外文文献批量下载的自动化解决方案。教程详细介绍了如何从数据库导出并清洗DOI信息,编写健壮的Python脚本进行批量下载,并包含错误处理与进阶优化技巧,旨在帮助科研人员将重复性劳动自动化,大幅提升文献收集效率。

weixin_29050513的博客 307

C#程序实现动态调用DLL (2)

3.        C#动态调用DLL中的函数 因为C#中使用DllImport是不能像动态load/unload assembly那样,所以只能借助API函数了。在kernel32.dll中,与动态库调用有关的函数包括[3]: ①LoadLibrary(或MFC 的AfxLoadLibrary),装载动态库。 ②GetProcAddress,获取要引入的函数,将符号名或标识号转换为DLL

chy2z的专栏 2504

『MaxKB 2.x 开发环境搭建』在Windows下运行最新源码的完整步骤

本文将详细介绍如何在Windows系统中完成MaxKB最新版(2.x)开发环境的搭建,包括前端、后端以及数据库的配置,确保开发者能够顺利启动项目。

老陈聊架构 586

如何在 C# 程序中注入恶意 DLL?

有了自定义注入的想法,接下来的实现步骤大概是这样的。注入一个线程到 C# 程序中。让程序加载一个 dll 文件。在 dll 中做一些我想做的业务逻辑。接下来新建一个 C++ 的动态链接库,在 DLLMain 入口函数的){{printf(" 总部,总部,我已经成功打入内部!break;}}要被加载的已经构建完毕,接下来就用 Win32 API 的实现远程注入,但注入之前需要做三件事情。获取 C# 程序的 进程句柄。在 C# 进程中申请一块内存空间,存放加载的 path 路径。

一线码农的专栏 2103

lammps案例:热导率模拟案例讲解(NEMD方法)

lammps计算热导率大体可以分为三种方法:EMD、NEMD、rNEMD。 本文介绍非平衡模拟(NEMD)热导率的计算方法。 NEMD下热导率计算公式为: k=dQ*dZ/dt k:热导率 dQ:能量通量。 dT/dZ:温度梯度。 非平衡态下计算热导率的原理是在材料的两端或者中间设置热源和冷源。 在热源输入热量,在冷源抽取等量的热量,在这个过程中计算材料内部会有热量的传递,产生温度梯度。 在lammps模拟中得到能量通量和温度梯度,代入公式即可求得热导率。 热量的输入方式有多种,如fix langevin

lammps_jiayou的博客 1万+

【MicroPython编程-ESP32篇:设备驱动】-BNO08X系列传感器驱动

BNO08X 系列(BNO085/BNO086)是一款系统级封装 (SiP),集成了三轴加速度计、三轴陀螺仪、磁力计以及运行 CEVA SH-2 固件的 32 位 ARM® Cortex™-M0+ 微控制器。SH-2 包含 MotionEngine™ 软件,该软件提供复杂的信号处理算法来处理传感器数据,并提供精确的实时 3D 姿态、航向、校准加速度和校准角速度,以及更高级的上下文输出。BNO08X 集成在一个 28 引脚 LGA 封装中,尺寸为 3.8mm x 5.2mm x 1.1mm。它兼容 Andro

视觉与物联智能 695

[导入]浅析.Net下的AppDomain编程

浅析.Net下的AppDomain编程文章来源:http://blog.csdn.net/21aspnet/archive/2004/10/29/158890.aspx 转载于:https://www.cnblogs.com/zhaoxiaoyang2/archive/2004/10/30/816250.html

weixin_30512089的博客 88

大模型工作流Dify面试题及参考答案

设计一个基于 Dify 的智能摘要与重点提取 Agent,需结合Prompt 工程、模型能力配置和工作流优化,确保对长文本的高效解析和关键信息提炼。1. 明确任务需求与输入输出输入:长文本内容(如文章、报告、会议记录)或文本 URL输出摘要:简洁概括原文核心内容,控制在原文长度的 10%-20%重点列表:分点列出关键数据、结论、行动项等可选:关键词提取、情感倾向分析示例场景输入:一篇 5000 字的行业报告。

大模型大数据攻城狮的专栏 2510

【转载】 浅析.Net下的AppDomain编程

浅析.Net下的AppDomain编程 收录于:http://blog.csdn.net/21aspnet/article/details/158890 2013-03-26 我们知道,进程是操作系统用于隔离众多正在运行的应用程序的机制。在.Net之前,每一个应用程序被加载到单独的进程中,并为该进程指定私有的虚拟内存。进程不能直接访问物理内存,操作系统通过其它的处理把这些虚拟内存映射到物理内...

weixin_33806509的博客 80

Probability and Statistics - 4th edition

Probability and Statistics - 4th edition

VC中sqlite的使用

在VC中对sqlite的使用,实现数据库大批数据的快速插入,读取数据库中的数据在ListCtrl中显示

Net下的AppDomain编程 [摘录]

最近在对AppDomain编程时遇到了一个问题,卸载AppDomain后,在内存中还保留它加载的DLL的数据,所以即使卸载掉AppDomain,还是无法更新它加载的DLL.看来只有关闭整个进程来更新DLL了. ----------------------------------------------------------------------------------------------...

weixin_33697898的博客 91

OV9734 DATASHEET,完整规格书

OV9734完整规格书,包括电气参数,尺寸规格,寄存器配置表等

Net下的AppDomain编程

我们知道,进程是操作系统用于隔离众多正在运行的应用程序的机制。在.Net之前,每一个应用程序被加载到单独的进程中,并为该进程指定私有的虚拟内存。进程不能直接访问物理内存,操作系统通过其它的处理把这些虚拟内存映射到物理内存或IO设备的某个区域,而这些物理内存之间不会有重叠,这就决定了一个进程不可能访问分配给另一个进程的内存。相应地,运行在该进程中的应用程序也不可能写入另一个应用程序的内存,这确保了任

jsjwql专栏 888

最新的sdio 4.0 spec 协议标准 带书签 高清完整PDF版

Part-E1-SDIO-Specification-Ver4.00-Final-120220.pdf:最新的sdio 4.0 spec 协议标准 带书签 高清完整PDF版,包括SDIO 接口的外设,SDIO 接口官方协议等。

.Net下的AppDomain编程 [摘录]

最近在对AppDomain编程时遇到了一个问题,卸载AppDomain后,在内存中还保留它加载的DLL的数据,所以即使卸载掉AppDomain,还是无法更新它加载的DLL.看来只有关闭整个进程来更新DLL了. ------------------------------------------------------------------------------------------...

weixin_30617561的博客 91

(转)浅析.Net下的AppDomain编程

http://tech.ccidnet.com/art/1136/20021114/30763_1.html?channelid=1649&wd=&searchword=appdomain&client=pub-3653458698766474&q=&domains=ccidnet.com&sitesearch=ccidnet.com我们知...

dench2001的博客 115

浅析 .Net的AppDomain编程

<br />我们知道,进程是操作系统用于隔离众多正在运行的应用程序的机制。在.Net之前,每一个应用程序被加载到单独的进程中,并为该进程指定私有的虚拟内存。进程不能直接访问物理内存,操作系统通过其它的处理把这些虚拟内存映射到物理内存或IO设备的某个区域,而这些物理内存之间不会有重叠,这就决定了一个进程不可能访问分配给另一个进程的内存。相应地,运行在该进程中的应用程序也不可能写入另一个应用程序的内存,这确保了任何执行出错的代码不会损害其地址空间以外的应用程序。在这种机制下,进程作为应用程序之间一个独立而安全的

249
上一篇: 如何根据字符串获取嵌入到程序中的图片等资源
下一篇: Teradata学习笔记
challwang
博客等级 码龄19年 2粉丝 5原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值