Domanda

Abbiamo un'applicazione gestita, che utilizza un assembly. Quell'assemblea utilizza un codice non gestito C ++.

Il codice C ++ gestita è in un DLL, che dipende da diversi altri DLL. Tutte queste DLL vengono caricate da questo codice. (Carichiamo tutte le dll che ImageCore.dll dipende dalla prima, in modo che possiamo dire quali sono mancanti, altrimenti sarebbe semplicemente presentarsi come ImageCore.dll non è riuscito a caricare, e il file di log darebbe nessun indizio sul perché).

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");
        }
    }
}

E questo codice è chiamato da

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

Il che è costruttore statico.

Da quanto posso capire che, non appena si cerca di utilizzare un oggetto ImageDoc, la dll che contiene tale assembly viene caricato e come parte di tale carico, il costruttore statico viene chiamato che a sua volta provoca diversi altre DLL a essere caricato pure. Quello che sto cercando di capire, è come si fa rimandiamo carico di quelle DLL in modo che non corriamo dab in questo blocco loader che viene buttato fuori a causa del costruttore statico.

Ho ricostruito così tanto insieme, cercando in:

  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

Ma io proprio non riesco a trovare un modo per ottenere queste DLL esterne a carico senza che ciò accada nel punto la classe sta caricando. Penso di aver bisogno di ottenere queste chiamate LoadLibrary fuori dal costruttore statico, ma non so come farli chiamati prima che sono necessari (tranne che per come è fatto qui). Io preferirei non dover mettere questo tipo di conoscenza delle DLL in ogni applicazione che utilizza questa assemblea. (E non sono sicuro che sarebbe anche risolvere il problema ....

La cosa strana è che l'eccezione appare solo accadere durante l'esecuzione all'interno del debugger, non durante l'esecuzione di fuori del debugger.

Come faccio a gestire caricare tali DLL senza correre afoul di:

LoadLibrary <- .NET loads the class from assembly dll 
DllMain 
LoadLibrary <- -Due to Static ctor 
DllMain
È stato utile?

Soluzione

LoaderLock è un MDA (Managed Debug Assistant) avviso dal debugger. Ti dice che non vi potrebbe essere un problema con il codice. Succede solo quando si esegue nel debugger perché è il debugger che sta facendo la MDA controlli di informarvi che in alcune circostanze una situazione di stallo " possono verificarsi".

Purtroppo non posso aiutarti molto oltre. La mia esperienza di LoaderLock è che (a) si tratta di un misterioso avvertimento che VS si dà, ma c'è ben poco supporto che ti dice cosa fare realmente per risolvere il problema, e (b) la nostra applicazione è in corso da 4 anni con un LoaderLock andando fuori (in DirectX, quindi non è nemmeno nel nostro codice) e non è mai in realtà causato un problema, oltre ad essere un fastidio fastidioso ogni volta che si corre nel debugger. YMMV naturalmente.

(È possibile disattivare il MDA in Debug -> Eccezioni nella sezione Assistenti Debug Gestito, ma ogni volta che si Ripristina le impostazioni, il maledetto MDA si riaccende)

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top