簡體   English   中英

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

[英]Mixed mode assemblies loaded in all appdomains

我們的應用程序設置了一個AppDomain,將一些模塊加載到其中。 這些模塊之一是使用舊版混合模式DLL與H5文件進行交互。 問題在於,一旦加載了混合模式DLL,就會在新的AppDomain中以及在應用程序啟動時創建的原始AppDomain中都放置一個句柄。

當我們卸載該AppDomain時,新AppDomain中的句柄自然會消失,但原始AppDomain中的句柄將保留並固定。 這導致托管堆的碎片化。

在混合模式源代碼中找不到任何可以解釋此行為的內容。 唯一看起來可疑的是使用本地靜態字符串的以下調用:

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

其中H5Utils::errorStack_.c_str()是本地靜態字符串。 但是,永遠不會調用此方法,並且在加載混合模式DLL時,模塊會立即加載到兩個AppDomain中。

有誰知道為什么要在兩個AppDomain中都創建一個句柄?

因此,我進一步研究了這個問題並找到了答案,所以我認為如果有人遇到相同的問題,我會回答我自己的問題。

將模塊同時加載到兩個AppDomain中的原因是由於使用了本地全局值和靜態成員值。 這實際上是有道理的,因為這些值是在本機堆上分配的,並且如果在多個AppDomain中使用此模塊,則很有可能您仍然希望共享這些值。

問題是當您不斷創建和銷毀AppDomain並加載這些類型的資源時,因為首先添加到正在運行的進程AppDomain的引用是靜態的,因此會導致固定。 這使托管堆碎片化,長時間運行的進程將開始消耗內存。

為了解決此問題,Microsoft添加了__declspec(appdomain) ,應將其添加到本機類型的全局變量中,以使它們僅駐留在創建模塊的AppDomain中。 啟用/clr:pure也將使它成為聲明。 msdn在appdomain的幫助中對此進行了詳細說明

最后的陷阱是,您必須了解#include文件。 例如, #include <string>將導致模塊在AppDomain之間共享,而#include <stdio.h>則不會。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM