Question

Nous avons une application gérée, qui utilise un ensemble. Cet ensemble utilise une partie non géré le code C ++.

Le code C ++ géré se trouve dans une dll, qui dépend de plusieurs autres DLL. Tous ces Dlls sont chargés par ce code. (On charge tous les dll que ImageCore.dll dépend en premier lieu, afin que nous puissions dire quels sont portés disparus, il aurait simplement apparaître comme ImageCore.dll n'a pas réussi à charger, et le fichier journal ne donnerait pas d'indices pour expliquer pourquoi).

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

Et ce code est appelé par

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

Ce qui est constructeur statique.

Pour autant que je peux le comprendre, dès que nous essayons d'utiliser un objet ImageDoc, la dll contenant cette assemblée est chargé et dans le cadre de cette charge, le constructeur statique est appelé à son tour provoque plusieurs autres DLL à être chargée aussi bien. Ce que je suis en train de comprendre, comment de sorte que nous ne courons pas reportons-nous le chargement de ces DLL smack dab dans ce verrou du chargeur qui est expulsé à cause du constructeur statique.

Je l'ai rapiécé autant ensemble en regardant:

  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

Mais je ne arrive pas à trouver un moyen d'obtenir ces DLL externes à charge sans que cela se produise au moment où la classe se charge. Je pense que je dois obtenir ces appels LoadLibrary sur le constructeur statique, mais je ne sais pas comment les obtenir appelé avant qu'ils ne soient nécessaires (sauf pour la façon dont il est fait ici). Je préférerais ne pas avoir à mettre ce genre de connaissance des DLLs dans toutes les applications utilisant cet ensemble. (Et je ne suis pas sûr que cela même résoudre le problème ....

La chose étrange est que l'exception ne semble se produire lors de l'exécution dans le débogueur, pas en cours d'exécution en dehors du débogueur.

Comment puis-je parviens à charger les DLL sans aller à l'encontre de:

LoadLibrary <- .NET loads the class from assembly dll 
DllMain 
LoadLibrary <- -Due to Static ctor 
DllMain
Était-ce utile?

La solution

LoaderLock est un MDA (Managed débogage Assistant) avertissement dans le débogueur. Il vous dit qu'il ya peut un problème avec le code. Il ne se produit que lors de l'exécution sous le débogueur, car il est le débogueur qui fait la MDA vérifie pour vous informer que dans certaines circonstances une impasse « peut se ».

Malheureusement, je ne peux pas vous aider beaucoup plus loin que cela. Mon expérience de LoaderLock est que (a) il est un avertissement mystérieux que VS vous donne, mais il y a peu de soutien précieux que vous dire ce qu'il faut réellement faire pour le résoudre, et (b) notre application fonctionne depuis 4 ans avec un LoaderLock aller au large (en DirectX, il est donc même pas dans notre code) et il n'a jamais effectivement causé un problème, autre que d'être un tracas ennuyeux à chaque fois que nous courons sous le débogueur. YMMV bien sûr.

(Vous pouvez désactiver la MDA dans Debug -> Exceptions dans la section Assistants Débogage gérés, mais chaque fois que vous Réinitialiser les paramètres, la putain MDA se rallume)

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top