.NET 4.0及更高版本的更新
这是一个早期提出的问题,当时在.Net 2.0时支持混合模式DLL的初始化问题严重,容易出现随机死锁。从.Net 4.0开始,混合模式DLL的初始化方式已经改变。现在有两个分离的初始化阶段:
- Native initialization,在DLL入口点调用,包括本机C++运行时设置和执行您的DllMain方法。
- Managed initialization,由系统加载器自动执行。
因为步骤#2是在加载程序锁之外执行的,所以不会出现死锁情况。详细信息请参见混合程序集的初始化。
为确保您的混合模式程序集可以从本机可执行文件中加载,您唯一需要检查的是将DllMain方法声明为本地代码。#pragma unmanaged
可以在这里帮助:
BOOL APIENTRY DllMain(HMODULE hModule,
DWORD ul_reason_for_call,
LPVOID lpReserved
)
{
... // your implementation here
}
同样重要的是,DllMain 可能直接或间接调用的任何代码也必须是非托管的。限制 DllMain 使用的功能类型是有意义的,这样可以跟踪所有从 DllMain 可达的代码,并确保它们都使用 #pragma unmanaged
编译。
如果编译器检测到 DllMain 没有声明为非托管,则会给出警告 C4747:
1> Generating Code...
1>E:\src\mixedmodedll\dllmain.cpp : warning C4747: Calling managed 'DllMain': Managed code may not be run under loader lock, including the DLL entrypoint and calls reached from the DLL entrypoint
然而,如果DllMain间接调用其他托管函数,编译器将不会生成任何警告,因此您需要确保这永远不会发生,否则您的应用程序可能会随机死锁。