简体   繁体   English

在所有appdomain中加载的混合模式程序集

[英]Mixed mode assemblies loaded in all appdomains

Our application sets up a AppDomain that we load some modules into. 我们的应用程序设置了一个AppDomain,将一些模块加载到其中。 One of these modules is using a legacy mixed mode DLL for interacting with H5-files. 这些模块之一是使用旧版混合模式DLL与H5文件进行交互。 The problem is that as soon as the mixed mode DLL is loaded a handle is placed both in the new AppDomain but also in the original AppDomain that was created when the application started. 问题在于,一旦加载了混合模式DLL,就会在新的AppDomain中以及在应用程序启动时创建的原始AppDomain中都放置一个句柄。

The handle in the new AppDomain naturally goes away when we unload that AppDomain but the handle in the original AppDomain remains and is pinned. 当我们卸载该AppDomain时,新AppDomain中的句柄自然会消失,但原始AppDomain中的句柄将保留并固定。 This leads to fragmentation of our managed heap. 这导致托管堆的碎片化。

I can't locate anything in the mixed mode source code that would explain this behavior. 在混合模式源代码中找不到任何可以解释此行为的内容。 The only thing which looks suspicious is the following call that uses a native static string: 唯一看起来可疑的是使用本地静态字符串的以下调用:

H5Utils::throwError( String^ message ) {
  String^ stackStr = gcnew String( H5Utils::errorStack_.c_str() );
  String^ myMessage = message + "\n\nError stack: " + stackStr;
  throw gcnew H5IOError( myMessage );
}

where H5Utils::errorStack_.c_str() is the native static string. 其中H5Utils::errorStack_.c_str()是本地静态字符串。 But this method never gets called and the module gets loaded into both AppDomains immediately when the mixed mode DLL is loaded. 但是,永远不会调用此方法,并且在加载混合模式DLL时,模块会立即加载到两个AppDomain中。

Does anyone know why a handle would be created in both AppDomains? 有谁知道为什么要在两个AppDomain中都创建一个句柄?

So I dug into this some more and have found an answer so I thought I answer my own question if someone runs into the same problem. 因此,我进一步研究了这个问题并找到了答案,所以我认为如果有人遇到相同的问题,我会回答我自己的问题。

The reason the module is loaded into both AppDomains is due to the usage of native global values and static member values. 将模块同时加载到两个AppDomain中的原因是由于使用了本地全局值和静态成员值。 This actually makes sense since these values are allocated on the native heap and if this module is used in more than one AppDomain there is a high probability that you still want to share these values. 这实际上是有道理的,因为这些值是在本机堆上分配的,并且如果在多个AppDomain中使用此模块,则很有可能您仍然希望共享这些值。

The problem is when you are constantly creating and destroying AppDomains and load these kinds of resources since the references that get added to the running process first AppDomain are static and hence causes pinning. 问题是当您不断创建和销毁AppDomain并加载这些类型的资源时,因为首先添加到正在运行的进程AppDomain的引用是静态的,因此会导致固定。 This makes the managed heap fragmented and long running process will start eating up memory. 这使托管堆碎片化,长时间运行的进程将开始消耗内存。

To solve this Microsoft added __declspec(appdomain) which should be added to globals of native types which makes them reside only in the AppDomain where the module was created. 为了解决此问题,Microsoft添加了__declspec(appdomain) ,应将其添加到本机类型的全局变量中,以使它们仅驻留在创建模块的AppDomain中。 Turning on /clr:pure will make this the declaration as well. 启用/clr:pure也将使它成为声明。 Most of this is described in msdn's help on appdomain msdn在appdomain的帮助中对此进行了详细说明

A final gotcha is that you must be aware of your #include files. 最后的陷阱是,您必须了解#include文件。 For instance #include <string> will cause the module to be shared between AppDomains while #include <stdio.h> will not. 例如, #include <string>将导致模块在AppDomain之间共享,而#include <stdio.h>则不会。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM