2

アセンブリを使用するマネージドアプリがあります。そのアセンブリは、管理されていないC++コードを使用します。

マネージC++コードはdll内にあり、他のいくつかのdllに依存しています。これらのDLLはすべて、このコードによってロードされます。(ImageCore.dllが依存するすべての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
4

1 に答える 1

3

LoaderLockは、デバッガーからのMDA(Managed Debugging Assistant)警告です。コードに問題がある可能性があることを示しています。これは、デバッガーで実行している場合にのみ発生します。これは、特定の状況下でデッドロックが「発生する可能性がある」ことを通知するMDAチェックを行うのはデバッガーであるためです。

残念ながら、それ以上のことはできません。LoaderLockの私の経験では、(a)VSからの不思議な警告ですが、それを解決するために実際に何をすべきかを説明するサポートはほとんどありません。(b)アプリケーションはLoaderLockで4年間実行されています。 (DirectXでは、コードにも含まれていません)、デバッガーで実行するたびに煩わしい手間がかかることを除けば、実際に問題が発生することはありません。もちろんYMMV。

([Managed DebuggingAssistants]セクションの[Debug]->[Exceptions]セクションでMDAを無効にできますが、これらの設定をリセットするたびに、いまいましいMDAが再びオンになります)

于 2010-03-19T21:19:43.027 に答える