线程为什么不能终止?

VenusC 2006-05-25 12:04:10
HANDLE hHdl;
HANDLE hStopEvent;
UINT __stdcall MyFunc(LPVOID pParam)
{
HANDLE hArr={hStopEvent,...}
int n = sizeof(hArr)/sizeof(HANDLE);
bool bRun = true;
while (bRun)
{
dwWait=WaitForMultipleObjects(n,hArr,FALSE,INFINITE);
switch (dwWait)
{
case WAIT_OBJECT_0:
bRun=false;
break;
case WAIT_OBJECT_0+1:
...
break;
default:
break;
}
}

_endthreadex(0);

}

void CreateMyThread()
{
hStopEvent=CreateEvent(NULL,TRUE,FALSE,NULL);
hHdl = (HANDLE)_beginthreadex(NULL, 0, MyFunc, NULL, CREATE_SUSPENDED, NULL);
ResumeThread(hHdl);
}

void FinalMyThread()
{
SetEvent(hStopEvent);
DWORD dwWait = WaitForSingleObject(hHdl, 20000L);
if (dwWait == WAIT_TIMEOUT)
{
GetExitCodeThread(hHdl, &dwExitCode);
if (dwExitCode == STILL_ACTIVE)
{
TerminateThread(hHdl, 1);
}
}
}

上述代码在DLL中实现,当调用FinalMyThread()后,每次都要等足20秒,进程才能退出。
单步跟踪的结果是:MyFunc()每当执行到_endthreadex(0)的时候就没响应了,所以每次都要通过TerminateThread来关闭线程。
MSDN上说non-MFC线程不能操作MFC对象,MyFunc中仅仅使用了一个包含了CString的类实例,但并没有操作其中的CString成员对象。

不知为什么线程不能终止?
...全文
259 12 打赏 收藏 转发到动态 举报
写回复
用AI写文章
12 条回复
切换为时间正序
请发表友善的回复…
发表回复
gonch 2006-05-26
  • 打赏
  • 举报
回复
有没有什么办法可以在卸载DLL时关闭一个线程,而又不通过DllMain()???
------------------------
你这个想法就不对。
不要所有的操作都希望能够系统自动处理,很多时候系统都会做一些莫名奇妙的操作,导致你的程序不正常的。
自己创建出来的线程都要自己来进行管理的,还是手动调用FinalMyThread吧。
aa3000 2006-05-25
  • 打赏
  • 举报
回复
为什么要调用 _endthreadex 呢?没有用吧

_endthreadex for
Terminate a thread created by _beginthread or _beginthreadex, respectively
pripor 2006-05-25
  • 打赏
  • 举报
回复
_endthreadex
VenusC 2006-05-25
  • 打赏
  • 举报
回复
找到原因了。
关闭线程是在DllMain(DLL_PROCESS_DETACH)的时候,这时系统会调用每个DLL的DllMain(DLL_THREAD_DETACH),包括当前DLL的,而当前DLL正在Wait,由于DllMain的顺序执行(参考《Windows核心编程》),所以后一次调用的DllMain()就一直不能被执行,于是线程的句柄就一直不是信号态的,WaitFor自然要超时啦。

有没有什么办法可以在卸载DLL时关闭一个线程,而又不通过DllMain()???
uoice 2006-05-25
  • 打赏
  • 举报
回复
可能是在DLL中创建的线程。
gonch 2006-05-25
  • 打赏
  • 举报
回复
程序看上去没有什么问题,现象是很奇怪。
看着_beginthread比较可疑,为什么要先挂起线程,你把挂起的选项去掉,然后把ResumeThread再试一下。
Practise_Think 2006-05-25
  • 打赏
  • 举报
回复
不要使用_endthreadex(0)来退出线程,直接return退出更好,另外TerminateThread()也是很危险的行为不到万不得已时最好不要使用,可以将bRun在另一线程里使用以使其能控制另一线程的运行或退出
Kudeet 2006-05-25
  • 打赏
  • 举报
回复
在线程外显式退出线程,应该用terminatethread.
MSDN说_endthreadex是在线程内用的, 是的, endthreadex一般不是用在函数的结构,是用在函数的中间需要退出线程的时候. 你已经到了线程函数的结尾,不再需要endthreadex.

在你的MyFunc你用return 0;代替_endthreadex(0);
VenusC 2006-05-25
  • 打赏
  • 举报
回复
To:pomelowu(羽战士)
“在线程外显式退出线程,应该用_endthreadex ”

_endthreadex()没有参数指明线程句柄,系统怎么知道是结束哪一个线程呢?
MSDN说_endthreadex是在线程内用的。
VenusC 2006-05-25
  • 打赏
  • 举报
回复
另外,如果想在DLL加载的时候启动一个线程,在DLL卸载的时候终止此线程,该如何实现?
VenusC 2006-05-25
  • 打赏
  • 举报
回复
不用_endthreadex也一样,在MyFunc结束的时候同样无响应。

FinalMyFunc()如果是在DllMain(DLL_PROCESS_DETACH)的情况下调用就出现上述情况,如果在DLL_PROCESS_DETACH之前调用,就可以很正常地退出,谁能解释一下?
pomelowu 2006-05-25
  • 打赏
  • 举报
回复
你得线程函数一直在WaitForMultipleObjects?线程函数无法退出。
线程函数退出的时候,_endthreadex 会被自动调用,所以你不需要写这么一个语句。
在线程外显式退出线程,应该用_endthreadex ,而不是TerminateThread,TerminateThread应该和CreateThread配合使用。

15,471

社区成员

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

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