猿问

我编写了一个Dll并且测试多线程,如下代码:

UINT __cdecl NowThread (LPVOID lpParam)
{
MessageBox(NULL,_T("开启新线程成功!"),_T("注入"),MB_OK);
return 0;
}
// CGameDllApp 初始化
BOOL CGameDllApp::InitInstance()
{
MessageBox(NULL,_T("DLL注入成功!"),_T("注入"),MB_OK); //仅这一句执行了

CWinThread* mythread = AfxBeginThread(
NowThread,
NULL,
THREAD_PRIORITY_NORMAL,
0,
0,
NULL
);
MessageBox(NULL,_T("开启线程完成!"),_T("注入"),MB_OK);
return CWinApp::InitInstance();
}

Dll加载后,仅执行了第一个MessageBox,后面的两个都没有执行
说明开启新线程不但失败了,并且也没有往下执行

郎朗坤
浏览 192回答 2
2回答

斯蒂芬大帝

这样解释或许你更能明白:创建线程会调用应用程序已经加载的所有DLL的DLLMain(参见DLLMain的文档中关于reason参数的说明),而DLLMain是不可以重入的,所以应用程序会死锁。也就是:BOOL CGameDllApp::InitInstance()在你的DLL的DLLMain中被调用,而你此时又创建线程,就会再次想调用你的DLL的DLLMain,但是CGameDllApp::InitInstance()所在的DLLMain并未执行完。所以就得等待完成,所以就AfxbeginThread等待自己完成操作,卡在这里了。

噜噜哒

系统是顺序调用D L L的D l l M a i n函数的。为了理解这样做的意义,可以考虑下面这样一个环境。假设一个进程有两个线程,线程A和线程B。该进程还有一个D L L,称为S o m e D L L . d l l,它被映射到了它的地址空间中。两个线程都准备调用C r e a t e T h r e a d函数,以便再创建两个线程,即线程C和线程D。当线程A调用C r e a t e T h r e a d来创建线程C时,系统调用带D L L _ T H R E A D _ AT TA C H值的S o m e D L L . d l l的D l l M a i n函数。当线程C执行D l l M a i n函数中的代码时,线程B调用C r e a t e T h r e a d函数来创建线程D。这时系统必须再次调用带有D L L _ T H R E A D _ AT TA C H值的D l l M a i n函数,这次是让线程D 执行代码。但是,系统是顺序调用D l l M a i n函数的,因此系统会暂停线程D的运行,直到线程C完成对D l l M a in函数中的代码的处理并且返回为止。当线程C完成D l l M a i n的处理后,它就开始执行它的线程函数。这时系统唤醒线程D,让它处理D l l M a i n中的代码。当它返回时,线程D开始处理它的线程函数。AfxBeginThread的核心还是CreateThread函数。所以请将AfxBeginThread函数从InitInstance里面拿出来,在导出个其他函数进行AfxBeginThread调用吧。
随时随地看视频慕课网APP
我要回答