Windows核心编程之线程终结
2016-04-27 21:47
260 查看
二、线程终结
1.线程函数的return返回(最好这样):
其中用线程函数的return返回, 而终止线程是最安全的, 在线程函数return返回后, 会清理函数内申请的类对象, 即调用这些对象的析构函数. 然后会自动调用 _endthreadex()函数来清理 _beginthreadex(...)函数申请的资源(主要是创建的tiddata对象).
2.调用 _endthreadex()函数 或 ExitThread()函数(最好不要)(结束线程自身):
如果使用这两种方法退出线程, 则不会执行线程函数的return语句, 所以就不会调用线程函数作用域内申请的类对象的析构函数, 会造成内存泄露.
剩下两种是在程序设计中一定要避免的.
3.用同一个进程中的另一个线程调用 TerminateThread()函数(必须避免)(所有线程都可以使用此方法);
4.终止该线程所在的进程(绝对避免);
但是要说_endthreadex完全没有用肯定是不对的,_endthreadex并不是一个过时的函数,正确的使用并不会带来问题。
比如在线程的主函数中,return是_endthreadex的一个良好替代,就像main函数里面return是exit()或ExitProccess()的良好替代一样,但是这不表示exit函数没用。比如线程调用了一个子函数,如果子函数决定退出线程,return是没用的,_endthreadex即可终结线程。
但是这个设计不好,因为可能造成LZ提出的资源泄漏。尤其考虑到后台线程终结后的资源泄漏比主线程的资源泄漏更要命(主线程退出后,进程就退出了,OS会清理一切资源,无所谓泄露不泄露,而子线程退出后主线程可能还会运行很久,并且可能有大量的同类型的子线程退出,会造成要命的泄露)
良好的设计还是返回线程的主函数,让threadproc来决定是不是要退出,从这个意义上说,_endthreadex没有必要。微软也指出,有些程序员就是要调用exit系列函数(ExitThread,ExitProccess等),没辙,只好提供了。
下面给出几个结束过程中发生事情:
1.资源有序释放(如操作系统分配资源,用到的C++类析构),返回线程退出代码,线程内核对象使用计数-1
2.操作系统相关资源释放;但象C++类并未析构,造成内存泄露;这里如果用_beginthreadex建立线程,而用ExitThread或者_endthread来释放线程,则线程放在堆上的线程数据块_tiddata也未释放,内存泄露;
3.该函数为异步函数,即通知操作系统终结线程后立即返回,而不管系统是否已经真的结束了线程。同时线程栈也不会释放
4.用ExitProgerss, TerminateProcess函数关闭进程后,进程会调用TerminateThread来关闭线程,效果如3,线程的栈没有释放,申请的对象资源也没释放。
说明:
参数:
返回值:无
说明:在线程结束后,会将线程内核对象中的ExitCode由STILL_ACTIVE转变为传入退出代码;与CreateThread对应
说明:
参数:
返回值:0表示失败,非0表示成功;
1.线程函数的return返回(最好这样):
其中用线程函数的return返回, 而终止线程是最安全的, 在线程函数return返回后, 会清理函数内申请的类对象, 即调用这些对象的析构函数. 然后会自动调用 _endthreadex()函数来清理 _beginthreadex(...)函数申请的资源(主要是创建的tiddata对象).
2.调用 _endthreadex()函数 或 ExitThread()函数(最好不要)(结束线程自身):
如果使用这两种方法退出线程, 则不会执行线程函数的return语句, 所以就不会调用线程函数作用域内申请的类对象的析构函数, 会造成内存泄露.
剩下两种是在程序设计中一定要避免的.
3.用同一个进程中的另一个线程调用 TerminateThread()函数(必须避免)(所有线程都可以使用此方法);
4.终止该线程所在的进程(绝对避免);
但是要说_endthreadex完全没有用肯定是不对的,_endthreadex并不是一个过时的函数,正确的使用并不会带来问题。
比如在线程的主函数中,return是_endthreadex的一个良好替代,就像main函数里面return是exit()或ExitProccess()的良好替代一样,但是这不表示exit函数没用。比如线程调用了一个子函数,如果子函数决定退出线程,return是没用的,_endthreadex即可终结线程。
但是这个设计不好,因为可能造成LZ提出的资源泄漏。尤其考虑到后台线程终结后的资源泄漏比主线程的资源泄漏更要命(主线程退出后,进程就退出了,OS会清理一切资源,无所谓泄露不泄露,而子线程退出后主线程可能还会运行很久,并且可能有大量的同类型的子线程退出,会造成要命的泄露)
良好的设计还是返回线程的主函数,让threadproc来决定是不是要退出,从这个意义上说,_endthreadex没有必要。微软也指出,有些程序员就是要调用exit系列函数(ExitThread,ExitProccess等),没辙,只好提供了。
下面给出几个结束过程中发生事情:
1.资源有序释放(如操作系统分配资源,用到的C++类析构),返回线程退出代码,线程内核对象使用计数-1
2.操作系统相关资源释放;但象C++类并未析构,造成内存泄露;这里如果用_beginthreadex建立线程,而用ExitThread或者_endthread来释放线程,则线程放在堆上的线程数据块_tiddata也未释放,内存泄露;
3.该函数为异步函数,即通知操作系统终结线程后立即返回,而不管系统是否已经真的结束了线程。同时线程栈也不会释放
4.用ExitProgerss, TerminateProcess函数关闭进程后,进程会调用TerminateThread来关闭线程,效果如3,线程的栈没有释放,申请的对象资源也没释放。
1. ExitThread()
VOID ExitThread( DWORD dwExitCode );
说明:
Header | Library |
winbase.h | coredll.lib |
dwExitCode: 指定线程的退出代码。可以通过GetExitCodeThread来查看一个线程的退出代码
返回值:无
说明:在线程结束后,会将线程内核对象中的ExitCode由STILL_ACTIVE转变为传入退出代码;与CreateThread对应
2. TerminateThread()
BOOL TerminateThread( HANDLE hThread, DWORD dwExitCode );
说明:
Header | Library |
winbase.h | coredll.lib |
hThread: 要结束的线程句柄
dwExitCode: 指定线程的退出代码。可以通过GetExitCodeThread来查看一个线程的退出代码
返回值:0表示失败,非0表示成功;
3. 判断线程是否结束
BOOL GetExitCodeThread( HANDLE hThread, LPDWORD lpExitCode );
//判断 bool IsThreadExit(HANDLE hThread) { bool bRet = false; DWORD dwExitCode; if(GetExitCodeThread(hThread, &dwExitCode)) { if(dwExitCode != STILL_ACTIVE) bRet = true; } else { //error err = GetLastError(); throw err; } return bRet; }
相关文章推荐
- c++第四次实验
- Java ArrayList 内部源码实现
- 第四次C++作业
- C# Socket流数据大小端读写封装
- java异常体系2
- golang + Atom 编程环境搭建
- [C#反射]C#中的反射解析及使用.
- java工程读取.properties配置文件
- poj2762 Going from u to v or from v to u? 强连通分量 + 拓扑排序
- java中final与static的区别
- Java基础
- 2015级C++第10、11周实践项目 继承和派生
- 搭建gpu的theano
- C++学习(一)——标准库类型之string全解析
- 使用javaFX编辑的学生管理系统
- php整理(四): mysql
- Struts2基础知识(三)
- 在web工程中使用spring(web.xml)
- Python打开文件,将list、numpy数组内容写入txt文件中
- php get_magic_quotes_gpc()函数用法介绍