有关dllmain中进程退出时的问题

sunnycrystal_2008 2008-07-09 06:49:53

我想让一个.exe的应用程序在结束之前调用dllmain中DLL_PROCESS_DETACH分支中的一个线程函数,如下:

DllMain(HINSTANCE hInstance, DWORD dwReason, LPVOID lpReserved)
{
if (dwReason == DLL_PROCESS_ATTACH)
hThreadHandle = (HANDLE)_beginthreadex(NULL, 0, &ThreadFun,
NULL, 0, &threadid);
if(WaitForSingleObject(hThreadHandle,INFINITE)==WAIT_O_OBJECT) //运行到此处就死住了,根本到不了线程函数
CloseHandle(hThreadHandle);
}
unsigned _stdcall ThreadFun(void *param)
{
printf("MyNewThread Is Begin");
return 0;
}
哪位高手能帮我解决一下,谢谢!
...全文
427 19 打赏 收藏 转发到动态 举报
写回复
用AI写文章
19 条回复
切换为时间正序
请发表友善的回复…
发表回复
小熊妞 2012-03-09
  • 打赏
  • 举报
回复
不要在DllMain中使用WaitForSingleObject,我的想法是设置一个全局变量g_bStopThread,等待线程结束

do
{
Sleep(SLEEP_INTERVAL);

} while (FALSE == g_bStopThread);

g_bExitThread = TRUE;
CloseHandle(hThread);
hThread = NULL;
sunnycrystal_2008 2008-07-14
  • 打赏
  • 举报
回复
对,楼上说得很有理,我今天试了,DisableThreadLibraryCalls真的不行,谢谢大家了,我准备结贴了,但是分数有限,大家不要嫌太少哦。
nevergone 2008-07-14
  • 打赏
  • 举报
回复
from 《windows 核心编程》:
通过进一步的研究,我终于发现了问题。当进程被创建时,系统也创建一个互斥对象。每个进程都有它自己的互斥对象,也就是说多个进程并不共享互斥对象。当线程调用映射到进程的地址空间中的D L L的D l l M a i n函数时,这个互斥对象负责对进程的所有线程实施同步。
当C r e a t e T h r e a d函数被调用时,系统首先创建线程的内核对象和线程的堆栈。然后它在内部调用Wa i t F o r S i n g l e O b j e c t函数,传递进程的互斥对象的句柄。一旦新线程拥有该互斥对象,系统就让新线程用D L L _ T H R E A D _ AT TA C H的值调用每个D L L的D l l M a i n函数。只有在这个时候,系统才调用R e l e a s e M u t e x,释放对进程的互斥对象的所有权。由于系统采用这种方式来运行,因此添加对D i s a b l e T h r e a d L i b r a r y C a l l s的调用,并不会防止线程被暂停运行。防止线程被暂停运行的唯一办法是重新设计这部分源代码,使得Wa i t F o r S i n g l e O b j e c t不会在任何D L L的D l l M a i n函数中被调用。

对于DLL_PROCESS_DETACH同样适用.
所以不要在DLL_PROCESS_DETACH中等待线程

重新设计你的线程吧
csx007700 2008-07-13
  • 打赏
  • 举报
回复
14 楼的方法好像不行啊
创建进程的时候,系统建立了一个互斥对象.每个进程都有自己的互斥对象,映射到DllMain时,互斥对象会合一个进程所有线程同步。
调用CreateThread时,系统首次创建线程内核对象。然后你调用
WaitForSingleObject传递互斥句柄,有了互斥对象系统又会调用每个Dll的DLL_THREAD_ATTACH,这时系统才会调用ReleaseMutex撤销互斥对象所有权。所以DisableThreadLibraryCalls()不能阻止死锁。你只能想办法不要调用WaitForSingleObject一系列函数才行。

sunnycrystal_2008 2008-07-13
  • 打赏
  • 举报
回复
to abomber2:
  加上你添加的函数就可以吗?明天我试试。
sunnycrystal_2008 2008-07-10
  • 打赏
  • 举报
回复
是写错了,应该是在DLL_PROCESS_DETACH下调用,不好意思。
我的实例只是随便写了一个,主要目的是要问在DLL_PROCESS_DETACH下能不能调用线程函数。
abomber2 2008-07-10
  • 打赏
  • 举报
回复
DllMain(HINSTANCE hInstance, DWORD dwReason, LPVOID lpReserved)
{
if (dwReason == DLL_PROCESS_ATTACH)

DisableThreadLibraryCalls(hInstance);
hThreadHandle = (HANDLE)_beginthreadex(NULL, 0, &ThreadFun,
NULL, 0, &threadid);
if(WaitForSingleObject(hThreadHandle,INFINITE)==WAIT_O_OBJECT) //运行到此处就死住了,根本到不了线程函数
CloseHandle(hThreadHandle);
}
unsigned _stdcall ThreadFun(void *param)
{
printf("MyNewThread Is Begin");
return 0;
}
huangyuelei01 2008-07-09
  • 打赏
  • 举报
回复
我从来也不知道WaitForSingleObject有WAIT_O_OBJECT这个返回值。
dbger 2008-07-09
  • 打赏
  • 举报
回复
建议看微软关于DLL的白皮书:
http://www.microsoft.com/whdc/driver/kernel/DLL_bestprac.mspx
IsItNothing 2008-07-09
  • 打赏
  • 举报
回复
你这样作是不合适的,应该再DLL_PROCESS_DETACH下调用
if(WaitForSingleObject(hThreadHandle,INFINITE)==WAIT_O_OBJECT) //运行到此处就死住了,根本到不了线程函数
CloseHandle(hThreadHandle);
}
另外你的实例程序我看了费解,不知道你要干什么.
IsItNothing 2008-07-09
  • 打赏
  • 举报
回复
你这样作是不合适的,应该再DLL_PROCESS_DETACH下调用
if(WaitForSingleObject(hThreadHandle,INFINITE)==WAIT_O_OBJECT) //运行到此处就死住了,根本到不了线程函数
CloseHandle(hThreadHandle);
}
另外你的实例程序我看了费解,不知道你要干什么.
sunnycrystal_2008 2008-07-09
  • 打赏
  • 举报
回复
不好意思,是写错了,应该是:
DllMain(HINSTANCE hInstance, DWORD dwReason, LPVOID lpReserved)
{
if (dwReason == DLL_PROCESS_DETACH)
hThreadHandle = (HANDLE)_beginthreadex(NULL, 0, &ThreadFun,
NULL, 0, &threadid);
if(WaitForSingleObject(hThreadHandle,INFINITE)==WAIT_O_OBJECT) //运行到此处就死住了,根本到不了线程函数
CloseHandle(hThreadHandle);
}
unsigned _stdcall ThreadFun(void *param)
{
printf("MyNewThread Is Begin");
return 0;
}

该线程函数不是死循环函数,如果不在dllmain()中调用,在其他地方调用是可行的。

请问一下dbger:
怎么用导出函数呢,能说得具体一点吗?
sunnycrystal_2008 2008-07-09
  • 打赏
  • 举报
回复
不好意思是写错了,应该是:
DllMain(HINSTANCE hInstance, DWORD dwReason, LPVOID lpReserved)
{
if (dwReason == DLL_PROCESS_DETACH)
hThreadHandle = (HANDLE)_beginthreadex(NULL, 0, &ThreadFun,
NULL, 0, &threadid);
if(WaitForSingleObject(hThreadHandle,INFINITE)==WAIT_O_OBJECT) //运行到此处就死住了,根本到不了线程函数
CloseHandle(hThreadHandle);
}
unsigned _stdcall ThreadFun(void *param)
{
printf("MyNewThread Is Begin");
return 0;
}
该线程函数不是死循环函数,在dllmain()以外的地方调用都是可以执行的。

还想问一下dbger怎么用导出函数呢,能说得具体一点吗?
sunnycrystal_2008 2008-07-09
  • 打赏
  • 举报
回复
不好意思,是写错了,应该是:
DllMain(HINSTANCE hInstance, DWORD dwReason, LPVOID lpReserved)
{
if (dwReason == DLL_PROCESS_DETACH)
hThreadHandle = (HANDLE)_beginthreadex(NULL, 0, &ThreadFun,
NULL, 0, &threadid);
if(WaitForSingleObject(hThreadHandle,INFINITE)==WAIT_O_OBJECT) //运行到此处就死住了,根本到不了线程函数
CloseHandle(hThreadHandle);
}
unsigned _stdcall ThreadFun(void *param)
{
printf("MyNewThread Is Begin");
return 0;
}

该线程函数不是死循环函数,如果不在dllmain()中调用,在其他地方调用是可行的。

请问一下dbger:
怎么用导出函数呢,能说得具体一点吗?
jwybobo2007 2008-07-09
  • 打赏
  • 举报
回复
DLL_PROCESS_DETACH通知中的函数怎么会在DLL_PROCESS_ATTACH里面执行,楼主写错了吧.
而且请问,该线程函数是死循环线程么?如果是,那么WaitForSingleObject(hThreadHandle,INFINITE)肯定会永远等待下去
dbger 2008-07-09
  • 打赏
  • 举报
回复
[Quote=引用 3 楼 sunnycrystal_2008 的回复:]
那如果我需要在dllmain()中调用线程函数怎么办呢,有什么好办法解决呢?
[/Quote]

建议用导出函数来处理。
sunnycrystal_2008 2008-07-09
  • 打赏
  • 举报
回复
那如果我需要在dllmain()中调用线程函数怎么办呢,有什么好办法解决呢?
stivenjia 2008-07-09
  • 打赏
  • 举报
回复
你在ThreadFun中插入一句MessageBox(NULL,"Test","Test",MB_OK);
你看看你的那个线程到底执行没?
第二WaitForSingleObject(线程句柄)我从来没这么用过并且ms也没有承诺过他的这个WaitForSingleObject的句柄可是个线程句柄
第三进程加载你这个dll时候会将其映射到进程虚拟执行空间,并执行dllmain(如果有)
dbger 2008-07-09
  • 打赏
  • 举报
回复
不要在DllMain中做启动线程的操作,因为会导致死锁。

15,471

社区成员

发帖
与我相关
我的任务
社区描述
VC/MFC 进程/线程/DLL
社区管理员
  • 进程/线程/DLL社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧