2010-03-19 3 views
2

Nous avons une application gérée, qui utilise un assemblage. Cet assembly utilise du code C++ non géré.Comment éviter le verrouillage de la chargeuse?

Le code C++ géré est dans une DLL, qui dépend de plusieurs autres DLL. Toutes ces DLL sont chargées par ce code. (Nous chargeons toutes les DLL dont dépend ImageCore.dll en premier, donc nous pouvons dire lesquelles sont manquantes, sinon il apparaîtrait juste comme ImageCore.dll n'a pas pu charger, et le fichier journal ne donnerait aucune indication quant à 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. Autant que je puisse le comprendre, dès que nous essayons d'utiliser un objet ImageDoc, la DLL qui contient cet assembly est chargée et dans le cadre de cette charge, le constructeur statique est appelé, ce qui à son tour provoque plusieurs autres DLL à charger aussi. Ce que j'essaie de comprendre, c'est comment différer le chargement de ces DLL afin de ne pas exécuter smack dab dans ce verrou de chargeur qui est expulsé à cause du constructeur statique.

J'ai rapiécé ce bien 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 peux pas sembler trouver un façon d'obtenir ces DLL externes à charger sans qu'il se passe au point le la classe est en cours de chargement. Je pense que j'ai besoin de sortir ces appels de LoadLibrary du constructeur statique, mais je ne sais pas comment les appeler avant qu'ils soient nécessaires (excepté comment c'est fait ici). Je préférerais ne pas avoir à mettre ce genre de connaissance des dlls dans chaque application qui utilise cette assemblée. (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 
+0

Quelle est votre question exactement? – Gabe

+0

Comment puis-je gérer pour charger ces DLL sans rencontrer les problèmes suivants: LoadLibrary <- .NET charge la classe à partir de la DLL d'assemblage DllMain LoadLibrary <- Due à Static ctor DllMain – boatcoder

Répondre

3

LoaderLock est un MDA (géré Debugging assistant) d'avertissement du débogueur Il vous indique qu'il y pourrait être un problème avec le code Cela n'arrive que lorsque vous courez Sous le débogueur parce que c'est le débogueur qui effectue les vérifications MDA pour vous informer que dans certaines circonstances, un blocage "peut se produire".

Malheureusement, je ne peux pas vous aider beaucoup plus loin que cela. Mon expérience de LoaderLock est que (a) c'est un avertissement mystérieux que VS vous donne, mais il y a un petit soutien précieux qui vous dit ce qu'il faut faire pour le résoudre, et (b) notre application fonctionne depuis 4 ans avec un LoaderLock s'en aller (dans DirectX, donc ce n'est même pas dans notre code) et cela n'a jamais réellement causé de 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 utilisez Réinitialiser les réglages, le dos sacrément MDA allume)

Questions connexes