问有关于dll和线程问题,解决就给分,没有答案宁肯扣信誉分也不结贴

qianyong325 2005-06-21 12:09:31
我在dll里创建了一个线程,查资料知道不能在InitInstance()中创建,这个我弄好了,那么在主程序结束的时候,我怎么退出线程呢?比如说主程序点击右上的关闭按钮,我尝试在dll的ExitInstance()函数里设置一个Event,然后在线程中WaitForSingleObject(),然后在ExitInstance()中waitForSingleObject(myhThread,INFINITE) ,但是到waitForSingleObject(myhThread,INFINITE)程序始终在等待,估计是线程没有退出!!!相同的代码如果不用在dll中直接在一个exe中,是没有问题的!!!!这个问题困扰我好几天了,请各位高手指教,解决了马上给分,如果分不够另外开贴送分!!
...全文
350 22 打赏 收藏 转发到动态 举报
写回复
用AI写文章
22 条回复
切换为时间正序
请发表友善的回复…
发表回复
qianyong325 2005-06-28
  • 打赏
  • 举报
回复
昨天后来公司忙,忘了结贴不好意思,马上就结
qianyong325 2005-06-27
  • 打赏
  • 举报
回复
to:linur(林曦)
在主程序的exitInstance里调用了::FreeLibrary(),应该是在::FreeLibrary()里面调用的dllApp::ExitInstance()吧?你的意思是说在::FreeLibrary()之后就先退出辅助线程然后在调用dllApp::ExitInstance这个函数是吗?
感谢你的解释,如果有什么可以继续说一下,晚上下班前就结贴了!分数都给你
qianyong325 2005-06-27
  • 打赏
  • 举报
回复
我如果另外设置一个handle来判断也就是说如果::WaitForSingleObject(hquit,INFINITE)中的hquit是在dll中另外创建的,而不是用pThread->m_hThread,那么我在调试的时候就可以跟踪到线程中::SetEvent(hquit);,在::WaitForSingleObject(hquit,INFINITE);就可以了,我想如果等待pThread->m_hThread就是你说的这种情况了,等下就结贴了,十分感谢你的帮助
linur 2005-06-27
  • 打赏
  • 举报
回复
我跟踪的结果显示主线程会先执行runtime函数ExitProcess来释放掉你的MyThread线程,并且释放掉其它资源,然后再调用dllApp::ExitInstance(),这个时候MyThread线程已经不存在了,所以主线程执行
bRun = false;时没有起作用,从而执行下一句::WaitForSingleObject(hquit,INFINITE)就阻塞了
xqk 2005-06-26
  • 打赏
  • 举报
回复
mark
linur 2005-06-26
  • 打赏
  • 举报
回复
to: qianyong325(帝王企鹅)
你把bRun = false; 放到dllApp::ExitInstance()里,注意仍然是主线程在执行这个函数。我已经在VC2003下写了测试过了,你这样做的结果虽然没有导致死锁,但是导致了主线程饿死现象,看看你写的代码
dllApp::ExitInstance()
{
bRun = false;
::WaitForSingleObject(hquit,INFINITE);

...
}
当主线程执行到bRun=false;之前就释放掉了,其原因是当程序退出时,主线程会先执行ExitProcess释放掉你的辅助线程,从而让你的MyThread线程非正常退出,也就是直接从while循环中退出,从而MyThread不能正常执行::SetEvent(hquit);这句代码再次唤醒主线程,导致让主线程永久睡眠了(饿死了)
不知道这样的解答你是否满意:)
umbrella1984 2005-06-26
  • 打赏
  • 举报
回复
看不出是哪里出问题了~有点诡异,楼主是否中间有调用过CloseHandle?
linur 2005-06-23
  • 打赏
  • 举报
回复
你用另外设置一个Handle hquit,在thread退出时设置这个SetEvent(hquit),就和我上面说的
在主线程里设置bRun = FALSE是一样的道理,你的方法也是让主线程去设置某个控制变量让线程退出.
而不是把控制代码放到线程的ExitInstance()
qianyong325 2005-06-23
  • 打赏
  • 举报
回复
那为什么我改了退出方式以后,在dll的exitInstance里就可以退出了,实际上我不能修改exe里的代码,我只知道主程序在退出的时候会调用一次FreeLibrary,FreeLibrary的时候应该会调用dll里exitInstance(),这个函数,这个时候应该还没有销毁资源吧?如果都销毁了,那我更改退出方式应该也不能解决问题!!!

欢迎继续讨论
qianyong325 2005-06-23
  • 打赏
  • 举报
回复
to: linur(林曦),你似乎没有明白我的解决办法。实际不是你说的而是
UINT MyThread(void * pParam)
{
while(bRun)
{
...
}

::SetEvent(hquit);
return 0;
}

dllApp::ExitInstance()
{
bRun = false;
::WaitForSingleObject(hquit,INFINITE);

...
}

to:tigerfox(风之力:=Doing.浪淘沙)
我知道用TerminateThread()也可以结束线程,而且结束之后还应该delete thread;否则有泄漏,但是这种方法是mircosoft极力反对的,几乎所有的windows编程经典著作都说应该让线程自己结束,连afxEndThread这个函数都不推荐使用,作为一个星星,你就这样教导新人吗?
tigerfox 2005-06-23
  • 打赏
  • 举报
回复
结束线程:

TerminateThread(hNetHandle[i],0);
CloseHandle(hNetHandle[i]);
linur 2005-06-22
  • 打赏
  • 举报
回复
to qianyong325(帝王企鹅)
你应该在主程序(就是应用程序对象类)的函数ExitInstance里(而不是DLL类那个ExitInstance)
写上
bRun = FALSE;
::WaitForSingleObject(hThread,INFINITE);
不用Wait函数也可以,你可以换为sleep(100);防止主线程退得太快而让辅助线程来不及正常退出

你原来的写法就会出来你说的问题,这是因为你虽然是创建在DLL中定义的线程,但是创建的线程
还是在主程序空间,这样你退出时,主程序会强行销毁所有的资源,因此你不应该让DLL的ExitInstance去控件线程的退出
qianyong325 2005-06-22
  • 打赏
  • 举报
回复
问题解决了,还是我自己解决的,郁闷~
我发现不能在dll的exitInstance函数里waitforsingleobject(p->m_hThread),这样会死锁,
其中, CWinthread *p = AfxBeginThead(Mythread,this);但是这样的用法在exe程序中是可以的,我现在折中的解决办法是另外设置一个Handle hquit,在thread退出时设置这个SetEvent(hquit),然后在
dll里的ExitInstance(){ ::WaitForSingleObject(hquit,INFINITE);}

虽然问题解决了,但是原理没弄懂,希望有懂得高手来给解释一下,为什么一样的代码在dll里会死锁,在exe程序里就可以用!!!


btw:感觉在csdn里想问个答案真tmd难,在c++板块好点,你们说那么多星星都是怎么升上去的?

goodboyws 2005-06-21
  • 打赏
  • 举报
回复
你的线程函数足够简单么,换成空循环试试,也许在别的地方阻塞。
younggle 2005-06-21
  • 打赏
  • 举报
回复
你的线程是怎么结束的?

线程函数
while(m_bThreadRun)
{
....
}

结束的方法:
m_bThreadRun = FALSE;
waitForSingleObject(myhThread,INFINITE);

但是线程一定要保证是一直在循环,能检测到 m_bThreadRun = FALSE


aben456 2005-06-21
  • 打赏
  • 举报
回复
extern "C" int APIENTRY DllMain(HINSTANCE hInstance, DWORD dwReason, LPVOID lpReserved)
{
UNREFERENCED_PARAMETER(lpReserved);
if (dwReason == DLL_PROCESS_ATTACH)
{
//dll attach,初始化
}
else if (dwReason == DLL_PROCESS_DETACH)
{
//ll detach
//可以试试让线程在这里退出
}
return 1;
}
aben456 2005-06-21
  • 打赏
  • 举报
回复
bRun = FALSE;
bRun是在哪里定义?
又是在哪里修改的?
修改成功了没有?
happytan 2005-06-21
  • 打赏
  • 举报
回复
HANDLE *m_ExitThread;全局变量

#define MaxWaitTimes 100 //线程每运转一次的间隔


*****线程******
for(;;)
{
DWORD dwRet=::WaitForSingleObject(m_ExitThread, MaxWaitTimes);
if (dwRet!=WAIT_OBJECT_0)
{
这里,你想干嘛就干嘛!
}
else
{
CloseHandle(m_ExitThread);
return 0;
}
}

*******结束线程*********
Close()
{
if(m_ExitThread!=NULL)
VERIFY(SetEvent(m_ExitThread));//设置线程退出

Sleep(MaxWaitTimes);//等待一个线程运转周期,确保线程退出
}
qianyong325 2005-06-21
  • 打赏
  • 举报
回复
to:linur(林曦)
我的线程是这样的

UINT MyFunc( LPVOID pParam )
{
while(bRun) // bRun是全局变量
{
if(::WaitForSingleObject(pParma->m_hEvent,10) == WAIT_OBJECT_0)
{
...... // 我自己的操作
}
}
return 0; // 当在ExitInstance里设置bRun = false,函数在这里停住了,跟进去是
// AfxEndthread() 死锁了,实在是不明白问题原因
}

// 下面是ExitInstance的代码
int CAlmMessApp::ExitInstance()
{
bRun = FALSE;
::WaitForSingleObject(p->m_hThread,INFINITE) // p = AfxBeginThread(DelayFunc,this);
}

现在的问题是如果退出的代码不在ExitInstance里,是没有问题的,如果是上面的样子,怎在
linur 2005-06-21
  • 打赏
  • 举报
回复
看来你创建的是MFC形式的DLL,那么你可以就在ExitInstance里结束你创建的线程
怎么结束,得取决于你的线程函数的写法
1.如果你的线程函数是没有循环,但是用了等待变量,那么你应该调用SetEvent唤醒它,
让线程自行结束就行
2.如果你的线程函数是有while(bContinue)这样的循环,你又在ExitInstance里
加入waitForSingleObject(myhThread,INFINITE)发现始终在等待,
这是因为你bContinue还是为true,或者你在线程函数中也有waitForSingleObject(h1)
这样的函数导致你的线程还在执行,那么你在ExitInstance里
直接设置它 bContinue=false ,若有等待变量的话,你还应该SetEvent(h1)
这样线程就自行结束了
加载更多回复(2)

15,471

社区成员

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

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