我有线程A正在创建另一个线程B,而线程A正在等待使用WaitForSingleObject等待线程B死亡。
问题是即使线程B从线程的“thread_func”返回,线程A 也不会发出信号!。
我知道因为我将trace(OutputDebugString)添加到thread_func(线程B的主函数)的末尾,我可以看到线程B完成了它的执行,但是线程A永远不会出现在WaitForSingleObject中。
现在,我还必须补充一点,这个代码是在一个COM对象中,当我调用regsvr32.exe(它被卡住了!)时,上面描述的场景正在发生,所以我相信线程A来自于的DLLMain。
为什么线程A没有发出信号的任何想法?!?!
答案 0 :(得分:14)
你可能遇到装载机锁的问题。 Windows,有一个内部关键部分,无论何时加载/卸载DLL或线程启动/停止(DllMain总是在该锁内部调用),它都会被锁定。如果您的等待线程A已将该关键部分锁定(即您正在等待DllMain的某个地方),而另一个线程B尝试关闭并尝试获取该加载器关键部分,则会出现死锁。
要查看死锁发生的位置,只需从VS IDE调试器运行您的应用程序,然后在它被卡住后,中断执行。然后查看所有正在运行的线程,并记下每个线程的堆栈。您应该能够跟踪每个堆栈并查看每个线程正在等待的内容。
答案 1 :(得分:4)
我认为@DXM是对的。关于你在DllMain
内可以做什么或不能做什么的文档是稀疏的,很难找到,但最重要的是你通常应该把它保持在最低限度 - 初始化内部变量等等,但是就是这个。
我要做的另一点是你通常应该不“调用”regsvr32.exe - 永远。
RegSvr32基本上只是一个使用LoadLibrary
将DLL加载到其地址空间的包装器,调用GetProcAddress
来获取名为DllRegisterServer
的函数的地址,然后调用该函数。这样做更清洁(并且最终更容易)自己完成这项工作:
HMODULE mod = LoadLibrary(your_COM_file);
register_DLL = GetProcAddress(mod, "DllRegisterServer");
if ( register_DLL == NULL) {
// must not really be a COM object...
}
if ( S_OK != register_DLL()) {
// registration failed.
}