2010-03-19 42 views
2

我們有一個託管應用程序,使用程序集。該程序集使用一些非託管C++代碼。如何避免裝載機鎖?

託管C++代碼是在一個DLL,這取決於其他幾個DLL。所有這些Dll都由此代碼加載。 (我們首先加載ImageCore.dll所依賴的所有dll,這樣我們就可以知道哪些是丟失的,否則它只會顯示爲ImageCore.dll加載失敗,並且日誌文件不會提供關於原因的線索)。

class Interop 
{ 
    private const int DONT_RESOLVE_DLL_REFERENCES = 1; 
    private static log4net.ILog log = log4net.LogManager.GetLogger("Imagecore.NET"); 

    [DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)] 
    private static extern IntPtr LoadLibraryEx(string fileName, IntPtr dummy, int flags); 
    [DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)] 
    private static extern IntPtr FreeLibrary(IntPtr hModule); 

    static private String[] libs = { "log4cplus.dll", "yaz.dll", "zlib1.dll", "libxml2.dll" }; 

    public static void PreloadAssemblies() 
    { 
     for (int i=0; i < libs.Length; ++i) { 
      String libname = libs[i]; 

      IntPtr hModule = LoadLibraryEx(libname, IntPtr.Zero, DONT_RESOLVE_DLL_REFERENCES); 
      if(hModule == IntPtr.Zero) { 
       log.Error("Unable to pre-load '" + libname + "'"); 
       throw new DllNotFoundException("Unable to pre-load '" + libname + "'"); 
      } else { 
       FreeLibrary(hModule); 
      } 
     } 

     IntPtr h = LoadLibraryEx("ImageCore.dll", IntPtr.Zero, 0); 
     if (h == IntPtr.Zero) { 
      throw new DllNotFoundException("Unable to pre-load ImageCore.dll"); 
     } 
    } 
} 

而這種代碼是由

public class ImageDoc : IDisposable { 
    static ImageDoc() 
    { 
     ImageHawk.ImageCore.Utility.Interop.PreloadAssemblies(); 
    } 
    ... 
} 

這是靜態構造函數調用。

盡我所知,只要我們嘗試使用ImageDoc對象,就會加載包含該程序集的dll,並且作爲該加載的一部分,將調用靜態構造函數,從而導致其他幾個DLL也要加載。我試圖弄清楚的是,我們如何推遲加載這些DLL,以便我們不會因爲靜態構造函數而將smack dab運行到正在被踢出的加載器鎖中。

我通過看這個拼湊在一起得多:

  1. http://social.msdn.microsoft.com/Forums/en-US/vsto/thread/dd192d7e-ce92-49ce-beef-3816c88e5a86
  2. http://msdn.microsoft.com/en-us/library/aa290048%28VS.71%29.aspx
  3. http://forums.devx.com/showthread.php?t=53529
  4. http://www.yoda.arachsys.com/csharp/beforefieldinit.html

但我似乎無法找到一個方式來獲得這些外部DLL加載沒有發生在點類正在加載。我想我需要將這些LoadLibrary調用從靜態構造函數中取出,但不知道如何在需要它們之前調用它們(除了這裏是如何完成的)。我寧願不必將這種dll的知識應用到使用此程序集的每個應用程序中。 (我不知道,甚至會解決這個問題....

奇怪的是,例外只出現在調試器中運行時,不會在調試器外部運行時發生。

如何管理加載這些DLL而不相抵觸運行:

LoadLibrary <- .NET loads the class from assembly dll 
DllMain 
LoadLibrary <- -Due to Static ctor 
DllMain 
+0

什麼是你的問題是什麼呢? – Gabe 2010-03-19 21:16:37

+0

我該如何設法加載這些DLL而不會碰到: LoadLibrary < - .NET從程序集DLL加載類 DllMain LoadLibrary < - 由於靜態ctor DllMain – boatcoder 2010-03-19 21:19:57

回答

3

LoaderLock是MDA(託管調試助手)警告從調試器它會告訴你,有可能與代碼中的問題只有在運行你的時候纔會發生因爲調試器正在使MDA檢查通知您,在某些情況下會發生死鎖「可能發生」。

不幸的是,我無法幫到你。我對LoaderLock的體會是(a)VS給你一個神祕的警告,但有一點寶貴的支持告訴你該怎麼解決它,(b)我們的應用程序已經運行了4年LoaderLock (在DirectX中,所以它甚至不在我們的代碼中),它實際上從來沒有引起任何問題,除了每次我們在調試器下運行時都是一個煩人的麻煩。 YMMV當然。

(您可以禁用調試MDA - >在託管調試助手一節,但每次重置這些設置時間例外,那該死的MDA重新開啓)