C#中AppDomain的使用

Posted

技术标签:

【中文标题】C#中AppDomain的使用【英文标题】:Usage of AppDomain in C# 【发布时间】:2009-03-20 10:52:40 【问题描述】:

AppDomain 在 C# 中最重要的用途是什么?

【问题讨论】:

请阅读我的博客,了解运行时加载 DLL 和使用 AppDomain 进行交叉通信的标准应用程序。 blog.vcillusion.co.in/… 【参考方案1】:

最重要的一个用途是您的代码必须有一个 - 即您用 C# 编写的所有内容都在 AppDomain 中执行。这很重要;-p

如果您的意思是附加应用程序域:

当使用插件和其他不受信任的代码时,它允许您进行隔离和卸载它们的能力(您不能卸载程序集 - 只能卸载整个应用程序域)。

我目前正在使用它来加载动态生成的 dll,以便我可以卸载它们。

它们还允许您设置不同的配置文件、信任级别等 - 但具有相关的复杂性和远程处理成本。

MSDN 有一个关于应用程序域的部分,here。

【讨论】:

【参考方案2】:

我不能告诉你最重要的用途是什么,因为这取决于具体情况。

AppDomain 对于应用程序的沙盒化部分很有用。您可以在 AppDomain 中加载扩展并再次卸载它们 - 这是您无法做到的。您可以将特定权限分配给 AppDomain。默认情况下,不同 AppDomain 中的对象不能相互访问。

AppDomain 可以被视为轻量级进程,因为它们为您提供了许多相同的功能。但是,与 Process 不同,新的 AppDomain 默认没有自己的线程。您必须自己管理 AppDomain 和线程。

此外,AppDomain 都共享同一个托管堆。这通常不是问题,但它可能会产生令人惊讶的效果,因为某些实例(如字符串)在 AppDomain 之间共享。对于常规使用,这不是问题,但如果您使用字符串进行锁定,不同 AppDomain 中的线程可能会相互影响。

【讨论】:

关于字符串的注意事项。 "AppDomains 都共享同一个托管堆。"这是否意味着它们也共享静态类或静态方法? @Mathematics 这只是意味着它们的堆都在 CLR 创建的同一个托管堆中。每个 AppDomain 不与任何其他共享其托管堆,否则它们将交叉引用实例,这是不允许的,并且 2 个 AppDomain 之间的数据交换只是按值复制【参考方案3】:

一般来说,使用 AppDomains 并不是日常的编码实践,这可以被认为是一个高级概念。但是,从这个简单的事情开始,更好地理解“AppDomain”这个词背后的概念很重要。

就架构而言,尽可能简单,即使在内存寻址方面,AppDomain 也是一个隔离容器,在其中加载和执行应用程序所需的所有程序集,即使这个概念更复杂详细解释(我希望这不是你的问题要深入)。

从那里开始,AppDomain 类首先用于获取对应用程序相关执行应用程序域的访问,这可以通过 Singleton 属性实现AppDomain.CurrentDomain 来完成。这样可以:

    获取已加载程序集的访问权限; 获得对 appdomain 共享数据槽的访问权限; intems marshalling,即从已创建域中加载的程序集中解开已创建实例。

那么,AppDomain 类用于:

    在同一进程中创建更多“域”; 在进程中执行程序集; 管理 appdomain 的加载/卸载过程。

查看新的 Microsoft 框架(尚未发布)MEF (Managed Extesibility Framework) 的代码可能会很有用,它真正基于 AppDomains 创建和卸载、动态加载的程序集等概念。

作为一个简单的例子和​​你可以用 AppDomains 做什么的例子,我可以分享这个link。

希望我回答了你的问题。

【讨论】:

【参考方案4】:

C# AppDomain 是一个逻辑隔离的容器,.NET 代码在其中运行。当您运行任何 .NET 代码时,它总是在默认的应用程序域中运行。

请观看这个 30 分钟的 youtube 视频 What is C# AppDomain ?,它更详细地解释了 AppDomain。

但还是让我试着更详细地解释一下。假设您获得了第三方 DLL,并且您想在您的应用程序中使用它。但是您也怀疑第三方可能有一些恶意代码,因此您希望在受限环境中运行第三方 DLL。比如你不想让第三方访问你的c:盘或者删除文件等等。

因此您可以创建两个 AppDomain,一个用于第三方,一个用于您自己的 C# 类。对于第三方应用程序域,您将应用它无法访问 c: 驱动器的安全约束,而对于您的 C# DLL,您将拥有一个不受限制的应用程序域。

【讨论】:

【参考方案5】:

请阅读我的博客,了解运行时加载 DLL 和使用 AppDomain 进行交叉通信的标准应用程序。 https://blog.vcillusion.co.in/sending-events-through-application-domain-boundary/

    DLL 的运行时加载和卸载:我在一个项目中工作,其中 DLL 由用户在运行时加载,在程序执行期间,使用反射执行方法并在程序运行期间卸载。 保护我的主执行程序:我们正在动态加载 DLL,因此动态加载的 DLL 中发生的任何异常都不会影响我的主 AppDomain。如果出现损坏情况,我们可以选择高效地再次卸载和加载 DLL。 跨AppDomain通信:我们可以在运行时在不同的AppDomain中动态加载任意两个DLL,使它们相互通信。

【讨论】:

以上是关于C#中AppDomain的使用的主要内容,如果未能解决你的问题,请参考以下文章

受限 AppDomain 中的 C# 类继承自位于主 AppDomain 中的其他类

C#里的应用程序域AppDomain

将 c# 程序集动态加载和卸载到 appdomain

C#、MAF、单独 AppDomain 中的未处理异常管理

C#基础知识之System.AppDomain类

C# - 从另一个 AppDomain 中的方法返回值