2010-03-19 6 views
2

어셈블리를 사용하는 관리되는 앱이 있습니다. 이 어셈블리는 관리되지 않는 C++ 코드를 사용합니다.로더 잠금을 피하려면 어떻게해야합니까?

Managed 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이 발생합니다. 또한로드 될 수 있습니다. 내가 알아 내려고하는 것은 정적 생성자로 인해 쫓겨나고있는이 로더 잠금에 smack dab를 실행하지 않도록 DLL의 로딩을 연기하는 방법입니다.

  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

은 귀하의 질문에 정확히 무엇 (당신은 디버그에서 MDA를 비활성화 할 수 있습니다> 관리 디버깅 도우미 섹션하지만 이러한 설정을 재설정 할 때마다에서 예외가, 망할 MDA 다시 켜집니다)? – Gabe

+0

로드하지 못하도록 해당 DLL을로드하는 방법 : LoadLibrary <- .NET이 어셈블리 DLL에서 클래스를로드합니다. DllMain LoadLibrary <- 정적 ctor로 인해 DllMain – boatcoder

답변

3

LoaderLock는 MDA (관리 디버깅 도우미) 디버거에서 경고입니다 그것은 코드에 문제가있을 수 있음을 알려줍니다 u를 실행할 때만 발생합니다. 어떤 상황에서는 교착 상태가 "이 될 수 있음"을 알리기 위해 MDA 검사를 수행하는 디버거이기 때문에 디버거를 사용할 수 없습니다.

불행히도 나는 그 이상으로 당신을 도울 수 없습니다. LoaderLock에 대한 나의 경험은 (a) VS가 당신에게주는 신비한 경고이지만, 실제로 그것을 해결하기 위해 무엇을해야하는지 알려주는 소중한 지원이 있습니다. (b) 우리의 응용 프로그램은 LoaderLock으로 4 년간 실행되었습니다. (DirectX에서 코드에 포함되어 있지 않기 때문에) 디버거로 실행할 때마다 짜증나는 번거 로움이 아닌 다른 문제가 발생하지 않았습니다. 물론 YMMV.

은 -

관련 문제