控件中调用有创建线程的动态库问题

red-fly 2010-05-31 10:26:22
首先说明,这个动态库在一般的EXE中调用是没有任何问题的,只是放到控件中就有问题了,不会退出。

动态库DLL使用纯C++写的,没有使用MFC。其中 有一个类CSystem,声明有其一个全局变量 CSystem g_sys
在这个类中,一开始会创建一个线程:
m_hThread = CreateThread( ..., thproc, ..., &m_hThreadID );

线程体内的代码逻辑如下:

DWORD thproc( LPVOID )
{
MSG msg;
while ( 1 )
{
if ( PeekMessage( msg, ... ) )
{
if ( msg.message == WM_QUIT )
break;
}
Sleep( 100 );
}
Trace( "线程退出\n" );
}


在CSystem的析构函数中退出线程:


PostThreadMessage( m_hThreadID, WM_QUIT );
DWORD dwRet = WaitForSingleObject( m_hThread, 10000 );


在一般的EXE中可以正常退出,即 最后的 WaitForSingleObject()可以很快返回,而在控件中却不会返回直到超时,这可以从打印出的“线程退出”判断线程体确实运行到了最后,但是从任务管理器中看不到线程数减少,即这个线程虽然运行到了最后,但它还是没有退出,确实搞不懂了,有请各位帮忙
...全文
169 26 打赏 收藏 转发到动态 举报
写回复
用AI写文章
26 条回复
切换为时间正序
请发表友善的回复…
发表回复
red-fly 2010-06-13
  • 打赏
  • 举报
回复
原因有待进一步验证,先结帐了
red-fly 2010-06-11
  • 打赏
  • 举报
回复
那看来我猜的是没错
过去就总是时不时出现线程退不出的问题,不过想了些办法,基本上也没有大问题,又有其它事情,就把它们放到一边了,不过这问题时不时地出来骚扰一下,这段时间算是有了一点点小空,就再思考了一下,还是有点儿收获的
comet 2010-06-11
  • 打赏
  • 举报
回复
你跟踪一下代码可以发现 main 函数 return 后 调动 ExitProcess 结束进程
下面是MSDN中ExitProcess 的说明:


Exiting a process causes the following:


1.All of the object handles opened by the process are closed.
2.All of the threads in the process, except the calling thread, terminate their execution. The entry-point functions of all loaded dynamic-link libraries (DLLs) are called with DLL_PROCESS_DETACH. After all attached DLLs have executed any process termination code, this function terminates the current process, including the calling thread.
3.The state of the process object becomes signaled, satisfying any threads that had been waiting for the process to terminate.
4.The states of all threads of the process become signaled, satisfying any threads that had been waiting for the threads to terminate.
5.The termination status of the process changes from STILL_ACTIVE to the exit value of the process.


可以看出ExitProcess时,系统把主线程外所有线程都停止了,然后再卸载动态库。即结束线程后才调用动态库中全局变量的析购函数。



你的问题只能在动态库中另外导出一个结束函数,结束函数中停止线程。
main返回前先调用该导出函数

red-fly 2010-06-10
  • 打赏
  • 举报
回复
各位都没有遇到过这样的问题吗?
red-fly 2010-06-08
  • 打赏
  • 举报
回复
昨天又有一种情况,就是在一个把这个DLL a封装到另一个DLL b中,然后exe调用b,结果这个线程也一样无法退出,就是在退出的时候,通过PostThreadMessage()向这个线程发送消息,结果这个线程连这个消息都收不到了,这和之前的退不出不一样(之前的是while退出,但线程退不出),太奇怪了。

后经进一步检查猜测,问题的产生原因可能如下:
在DLL中,线程t是在一个全局类(声明有一个其类型的全局变量)的构造函数中创建,在其析构函数中停止。而此类的析构,是在DLL被卸载的过程中调用的,那么这个时候,在不同类型的程序中,其卸载的过程可能不尽相同,在有些情况下,在运行到这个析构函数时,有关的程序消息机制和其它的辅助变量或者逻辑等已经不完全存在,所以会造成当线程退出时,WaitForSingleObject()收不到信号而无法返回,或者是向线程发送消息时,线程收不到。
这个原因系猜测,验证起来可能比较麻烦,还没有想出办法呢
red-fly 2010-06-07
  • 打赏
  • 举报
回复
在后面加上
ExitThread();
的结果还是一样

等待高手
sunlin7 2010-06-03
  • 打赏
  • 举报
回复
没有遇到过类似问题,也无法猜测原因,但楼主可以在
Trace( "线程退出\n" );
后面加上
 ExitThread();
看一下是否会有用。
red-fly 2010-06-03
  • 打赏
  • 举报
回复
大家继续,这个问题有点迷糊,可能是内部分有什么联系或者注意的地方但我不知道
red-fly 2010-06-02
  • 打赏
  • 举报
回复
up一下,各位帮忙了
red-fly 2010-06-02
  • 打赏
  • 举报
回复
是的,理论上应该是退出了,但是它确实没有退出,判断方法如下:

1. WaitForSingleObject()没有返回
2. 从任务管理器里看,线程数确实没有减少

刚开始的时候,以为是线程退出了,只是由于某种原因导致WaitForSingleObject()没有收到信号而不返回,但后来查看任务管理器中的线程数没有减少,才确认线程确实没有退出
oyljerry 2010-06-02
  • 打赏
  • 举报
回复
[Quote=引用 16 楼 jszj 的回复:]

注意:while()循环已经退出,是线程没有退出
[/Quote]
如何判断线程没有退出的? 线程函数是否返回..返回了的话,理论上这个线程就会结束了
red-fly 2010-06-02
  • 打赏
  • 举报
回复
注意:while()循环已经退出,是线程没有退出
zpf82118 2010-06-02
  • 打赏
  • 举报
回复
while(1)
必须手动结束,线程才会退出
具体有好几种方法,可搜索一下
red-fly 2010-06-01
  • 打赏
  • 举报
回复
在析构中基本上是这样的:

if ( m_hThread != NULL )
{
PostThreadMessage( m_hThreadID, WM_QUIT );
DWORD dwRet = WaitForSingleObject( m_hThread, 10000 );
if ( 超时 )
{
强制结束线程
}
CloseHandle( m_hThread );
m_hThread = NULL;
m_hThreadID = 0;
}

所以,在CreateThread()之后就直接调用CloseHandle( m_hThread );不妥,而且这个不是问题的关键
red-fly 2010-06-01
  • 打赏
  • 举报
回复
在一般的exe中:
程序退出 -> Dll卸载 -> CSystem 析构 -> 停止线程:
PostThreadMessage( m_hThreadID, WM_QUIT ); -> 线程退出 -> WaitForSingleObject( m_hThread, 10000 );立即返回 -> 整个程序正常退出

在控件ocx中:
程序退出 -> 卸载控件ocx -> Dll卸载 -> CSystem 析构 -> 停止线程:
PostThreadMessage( m_hThreadID, WM_QUIT ); -> 线程运行到最后一行(已退出while循环) -> WaitForSingleObject()超时 -> 强制结束线程 -> 整个程序退出
zhou1xp 2010-06-01
  • 打赏
  • 举报
回复
m_hThread = CreateThread( ..., thproc, ..., &m_hThreadID );
下面调用close(m_hThread ),核心编程里面说线程创建的时候计数为2
red-fly 2010-06-01
  • 打赏
  • 举报
回复
哦,控件是指ocx
zhou1xp 2010-06-01
  • 打赏
  • 举报
回复
楼主能够具体点么,应该是你的消息被MFC的默认处理程序处理了
red-fly 2010-06-01
  • 打赏
  • 举报
回复
PostThreadMessage( m_hThreadID, WM_QUIT );
确实有效,上面有说,Trace( "线程退出\n" );此行已经执行过了

to oyljerry:
那里说的是接收PostThreadMessage()消息的问题,我这里的线程已经接收到,并且确实退出了while循环,也已经到了线程体的最后一行,但线程实际上并没有真正退出来(任务管理器中的线程数不减少)
向立天 2010-06-01
  • 打赏
  • 举报
回复
我还是没明白你说的控件是什么意思
按钮消息?
加载更多回复(6)

15,471

社区成员

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

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