多个 .NET AppDomain 的代码示例
您可以在单个进程中运行多个应用程序域,其隔离级别与单独进程中的隔离级别相同,但不会产生跨进程调用或在进程之间切换的额外开销。
我想更多地了解如何/为什么在其应用程序中实际使用多个 AppDomain。谁能提供一个带有实际代码片段的示例吗?
From What is a .NET Application Domain?:
You can run several application domains in a single process with the same level of isolation that would exist in separate processes, but without incurring the additional overhead of making cross-process calls or switching between processes.
I would like to understand more about how/why one would actually use multiple AppDomains in their application. Can anyone provide an example with actual code snippets?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
阅读 MSDN 实际上提供了一些很好的信息。
http://msdn.microsoft.com/en-us/library/system .appdomain.aspx
--丹
Reading the MSDN actually provides some good information.
http://msdn.microsoft.com/en-us/library/system.appdomain.aspx
--Dan
我在以下上下文中使用了它(现在没有方便的代码来发布)
这样做的好处是您可以卸载加载到新创建的 AppDomain 中的程序集。如果您在主 AppDomain 上一遍又一遍地加载更多程序集,您的 AppDomain 将急剧增长。创建单独的 AppDomain 允许您在每次检查后卸载,从而卸载加载到该域的所有程序集,因此主 AppDomain 保持干净。
I have used this in the following context (don't have the code handy with me right now to post)
The benefit of this is that you can unload assemblies loaded into the newly created AppDomain. If you are doing this on your main AppDomain over and over again loading more assemblies, your AppDomain will grow monstrously. Creating a separate AppDomain allows you to unload after each inspection which in turn unload all the assemblies loaded to that domain hence the main AppDomain remains clean.
对于 .NET 应用程序在其(单个)进程中创建多个
AppDomain
实例来说,一个非常有用的场景是管理跨域的静态变量范围概念相关的对象实例的一些大集合。例如,考虑一个数据库应用程序,其中 90% 的代码管理一组相互关联的 .NET 对象,这些对象包含属于同一对象的各种表、行以及其他视图或数据实体。顶级数据库。在为数据库本身编写代码时,最好让该对象图中的每个子实例都是自给自足的,这意味着每个对象单独携带(通过包含)足够的信息来确定它需要关联的任何/所有上下文数据库的其余部分,无需任何外部引用。这允许您传递任何类型的次要实体,而不必担心它内部可能需要什么额外的上下文。
这种便利的代价是整个应用程序中的每个次要子对象都会携带其所需的上下文作为内部字段。如果应用程序还需要支持多个数据库,例如允许在数据库之间进行比较、导入或导出操作(例如代码的其他10%),那么每个对象的上下文必须包含直接或间接区分它最终属于哪个数据库的信息。
这些额外的信息可能会导致内存膨胀,尤其是在数量较多的低级实例中,并且对于单个给定的“普遍”数据库,根据定义,这种携带的上下文中的大部分将是重复的。
AppDomain
来救援... 相反,代码的数据库部分可以与每个数据库的不同AppDomain
相关联。由于静态变量的作用域是其AppDomain
,因此您可以将有关数据库的顶级信息与AppDomain
相关联,并且每个次要实例本质上都会知道它属于哪个数据库,要么相对于 AppDomain.CurrentDomain 静态属性,要么简单地引用您定义的静态字段、属性和方法,所有这些都不需要任何额外的每个实例字段。请注意,数据库间(即 10% 的部分)代码通过这种方式一次只能引用一个数据库。在此类操作期间,必须显式引用任何其他数据库(以传统方式)。然而,对于大部分代码来说,这种技术可以消除跨所有这些上下文字段部署的潜在数百万个对象引用。如果您拒绝全局单例的想法,请注意
AppDomain.CurrentDomain
已经存在于您的 .NET 代码中 - 那么为什么不好好利用它呢!An extremely useful scenario for a .NET application to create multiple
AppDomain
instances within its (single) process is to manage the scope of static variables across some large collection of conceptually-related object instances.For example, consider a database app where 90% of the code manages a set of inter-related .NET objects that comprise the various tables, rows, and other view or data entities which all belong to the same top-level database. In writing the code for the database itself, it is nice to have each of the sub-instances in this object graph be self-sufficient, meaning each object alone carries (by containment) enough information to determine any/all context it needs to relate to the rest of the database, without demanding any external reference. This allows you to pass around any type of minor entity without worrying about what additional context it might internally require.
The price of this convenience is that every minor sub-object throughout the app then carries the context it requires as an internal field. If the app also needs to support multiple databases, for example to allow for comparing, importing, or exporting operations between databases (the other 10% of your code, say), then the context for every object must include information to distinguish, directly or indirectly, ultimately which database it belongs to.
This extra information can lead to memory bloat, especially in the more numerous low-level instances, and for a single, given "prevailing" database, much of this carried context will, by definition, be duplicative.
AppDomain
to the rescue... Instead, the database portion of your code can be associated with a distinctAppDomain
for each database. Since static variables scoped to theirAppDomain
, you can associate the top-level information about the database with theAppDomain
, and every minor instance will inherently know which database it belongs to, either relative theAppDomain.CurrentDomain
static property, or by simply referencing static fields, properties, and methods you define, all without having any extra per-instance fields.Note that the inter-database (that 10% part) code can only reference one database at a time this way. Any additional database(s) have to be referenced explicitly (in the traditional way) during such operations. For the main bulk of the code, however, this technique could eliminate potentially millions of object references deployed across all those context fields. And if you resist the idea of global singletons, note that
AppDomain.CurrentDomain
exists in your .NET code already--so why not put it to good use!我开发了一款(主要是)C++ 软件,该软件允许用户使用 C# 或 VB.NET 编写脚本来自动化应用程序。该应用程序还有一些用 C# 编写的组件。它使用一个 AppDomain 作为程序组件,使用另一个 AppDomain 来沙箱脚本。
脚本的最初实现为每个脚本创建了一个 AppDomain,但事实证明这太慢并且阻止了一些有用的脚本行为,因此我们为脚本引擎使用了一个永久 AppDomain。
I worked on a piece of (mostly) C++ software that allowed users to write scripts to automate the application using C#, or VB.NET. The application also had a few of its components written in C#. It used one AppDomain for the program components, and another to sandbox the scripts.
The original implementation of scripting created an AppDomain for each script, but that proved to be too slow and it prevented some useful script behaviors, so we went to one permanent AppDomain for the script engine.
您可能想使用一个来模拟 IIS 的处理。您需要一个长时间运行的进程,该进程会泄漏内存。您可以跟踪 AD 上已处理的请求数量,以及达到阈值的请求,然后启动新请求。当旧的完成所有处理后,将其卸载并让 CLR 清理一些应用程序垃圾。
别问我怎么知道这些。 :)
如果您想在不同的安全上下文中运行代码,您也可以这样做。
You might want to use one to simulate the processing of IIS. You need a long running process that leaks memory. You can keep track of how many requests on AD has processed and one you reach a threshold, spin up a new one. When the old one has finished all processing unload it and let the CLR clean up some of the app junk.
Don't ask me how I know this. :)
You might also do this if you want to run code in different security contexts.