Ale*_*lex 4 c++ windows dll multithreading
我知道我无法从DllMain创建线程,但在DLL中创建线程的正确方法是什么?
我试图创建一个包装它的类并声明该类的全局实例,但WaitForSingleObject在类的析构函数中挂起,即使我确定该线程已退出.
这是我从exe加载DLL的示例程序:
#include <Windows.h>
#include <iostream>
using namespace std;
int main(int argc, TCHAR* argv[])
{
HMODULE module = LoadLibraryA("dll.dll");
Sleep(500);
if (module) FreeModule(module);
else cout << "failed to load library...\n";
return 0;
}
Run Code Online (Sandbox Code Playgroud)
这是dll代码:
#include <Windows.h>
#include <iostream>
using namespace std;
class X
{
HANDLE thread = NULL;
static DWORD WINAPI run_thread(LPVOID param)
{
cout << "dll.cpp: thread started\n";
Sleep(1000);
cout << "dll.cpp: thread is exiting\n";
return 0;
}
public:
X()
{
DWORD tmp;
thread = CreateThread(NULL, 0, run_thread, NULL, 0, &tmp);
if (thread == NULL)
{
cout << "failed to create thread\n";
throw 1;
}
}
~X()
{
if (thread != NULL)
{
cout << "joining thread...\n";
DWORD ret = WaitForSingleObject(thread, INFINITE);
cout << "result from waiting: " << ret << "\n";
thread = NULL;
}
}
}x;
BOOL APIENTRY DllMain(HMODULE hModule, DWORD reason, LPVOID lpReserved)
{
switch (reason)
{
case DLL_PROCESS_ATTACH:
cout << __FUNCTION__ << " reason DLL_PROCESS_ATTACH\n";
break;
case DLL_THREAD_ATTACH:
cout << __FUNCTION__ << " reason DLL_THREAD_ATTACH\n";
break;
case DLL_THREAD_DETACH:
cout << __FUNCTION__ << " reason DLL_THREAD_DETACH\n";
break;
case DLL_PROCESS_DETACH:
cout << __FUNCTION__ << " reason DLL_PROCESS_DETACH\n";
break;
}
return TRUE;
}
Run Code Online (Sandbox Code Playgroud)
这是程序输出:
DllMain reason DLL_PROCESS_ATTACH
DllMain reason DLL_THREAD_ATTACH
dll.cpp: thread started
DllMain reason DLL_PROCESS_DETACH
joining thread...
dll.cpp: thread is exiting
<- notice how WaitForSingleObject hangs,
even though the thread has exited
Run Code Online (Sandbox Code Playgroud)
这种方法有什么问题?
如果我碰巧从run_thread中删除Sleep(1000),以便线程在调用WaitForSingleObject之前完成,那么它不会挂起:
DllMain reason DLL_PROCESS_ATTACH
DllMain reason DLL_THREAD_ATTACH
dll.cpp: thread started
dll.cpp: thread is exiting
DllMain reason DLL_THREAD_DETACH
DllMain reason DLL_PROCESS_DETACH
joining thread...
result from waiting: 0
Run Code Online (Sandbox Code Playgroud)
我不明白这个区别,这也不是一个选项,因为线程的目的是在没有发信号通知DLL_PROCESS_DETACH的情况下不断循环.
我知道我无法从DllMain创建线程,但在DLL中创建线程的正确方法是什么?
在主应用程序加载了dll(隐式或显式通过LoadLibrary)之后,它会调用你的dll导出的一些函数,它可以做任何你喜欢的事情,包括启动线程.
我试图创建一个包装它的类并声明该类的全局实例
全局对象的初始化(破坏)DllMain也在内部发生; DllMainCRT采用了"真正的" 入口点(这是MSDN谈论的那个入口点),它使用它来初始化(破坏)全局变量和co.并且然后调用你的DllMain.
在这个类似问题的答案中(它LoadLibrary不是CreateThread,而是大部分也适用于这种情况),你可以找到更多的细节.
这种方法有什么问题?
你试图在里面做复杂的事情是错误的,DllMain特别是那些明确不鼓励的东西; 理想情况下DllMain应该是空的或做非常琐碎的工作.
最大的可能是,在这种特定的情况下,线程被终止试图再次拨打DllMain了DLL_THREAD_DETACH通知,但被锁定,或者是因为有防止并发访问的隐含互斥体DllMain,或因为Windows是明确禁止一个DLL_THREAD_DETACH从后抵达的通知DLL_PROCESS_DETACH.
这不会让我感到惊讶 - 毕竟,正如Hans Passant指出的那样,FreeLibrary代码仍在运行时调用显然是未定义的行为.这不是一个特定的函数(FreeLibraryAndExitThread)来让一个持有对库的引用的线程原子地释放库并自杀的机会.
| 归档时间: |
|
| 查看次数: |
2460 次 |
| 最近记录: |