.NET 4.0 和更多最新框架的更新
这是 .Net 2.0 时提出的一个老问题,当时对混合模式 DLL 的支持存在严重的初始化问题,容易出现随机死锁。从 .Net 4.0 开始,混合模式 DLL 的初始化发生了变化。现在有两个独立的初始化阶段:
- 本机初始化,在 DLL 的入口点调用,包括本机 C++ 运行时设置和 DllMain 方法的执行。
- 托管初始化,由系统加载程序自动执行。
由于第 2 步是在 Loader Lock 之外执行的,因此没有死锁。详细信息在混合程序集的初始化中进行了描述。
为了确保您的混合模式程序集可以从本机可执行文件加载,您唯一需要检查的是 DllMain 方法是否被声明为本机代码。#pragma unmanaged
可以在这里提供帮助:
#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 间接调用一些其他托管函数,编译器不会生成任何警告,因此您需要确保永远不会发生,否则您的应用程序可能会随机死锁。