質問
アセンブリを使用するマネージド アプリがあります。このアセンブリでは、アンマネージ C++ コードが使用されています。
マネージ 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 が次のように読み込まれます。良い。私が理解しようとしているのは、静的コンストラクターが原因で追い出されるこのローダーロックに直接アクセスしないように、これらの DLL のロードをどのように遅らせるかということです。
私は以下を見てこれだけをまとめました:
- http://social.msdn.microsoft.com/Forums/en-US/vsto/thread/dd192d7e-ce92-49ce-beef-3816c88e5a86
- http://msdn.microsoft.com/en-us/library/aa290048%28VS.71%29.aspx
- http://forums.devx.com/showthread.php?t=53529
- 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
解決
LoaderLockは、MDA(マネージドデバッグアシスタント)の警告デバッガからのです。これは、コードに問題があり、のかもしれないのことを示しています。デバッガの下で実行されているとき、いくつかの状況下というデッドロックをあなたに知らせるために、MDAのチェックを行っているデバッガですので、それだけで「 に発生する可能性があり、」起こります。
残念ながら、私はそれよりもはるかにさらにあなたを助けることはできません。 LoaderLockの私の経験では、その()、それはVSはあなたを与えること神秘的な警告ですが、実際にそれを解決するために何をすべきかを伝える貴重な少しのサポートがあり、および(b)は、当社のアプリケーションがLoaderLockと4年前から実行されていますオフに行く(DirectXの中で、それも我々のコードではありません)、それは実際に私たちは、デバッガの下で実行するたびに迷惑な手間をかけている以外の問題は、発生したことがないです。もちろん、YMMVます。
-
(デバッグでMDAを無効にすることができます>管理デバッグアシスタントセクションでの例外がありますが、それらの設定をリセットするたびに、気MDAはオンに戻ります)