线程的handle用处:

线程的handle是指向“线程的内核对象”的,而不是指向线程本身.每一个内核对象仅仅是内核分配的一个内存块,而且仅仅能由内核訪问。该内存块是一种数据结构,它的成员负责维护对象的各种信息(eg: 安全性描写叙述,引用计数等)。

CloseHandle()

在CreateThread成功之后会返回一个hThread的handle,且内核对象的计数加1,CloseHandle之后,引用计数减1,当变为0时,系统删除内核对象。

可是这个handle并不能全然代表这个线程,它不过线程的一个“标识”,系统和用户能够利用它对对应的线程进行必要的操纵。假设在线程成功创建后,不再须要用到这个句柄,就能够在创建成功后,线程退出前直接CloseHandle掉,但这并不会影响到线程的执行。

不运行CloseHandle() 带来的后果:

若在线程运行完之后,没有通过CloseHandle()将引用计数减1,在进程运行期间,将会造成内核对象的泄露,相当与句柄泄露,但不同于内存泄露, 这势必会对系统的效率带来一定程度上的负面影响。可是,请记住,当进程结束退出后,系统仍然会自己主动帮你清理这些资源。可是在这里不推荐这样的做法,毕竟不是 一个良好的编程习惯!

( 应用程序执行时,有可能泄露内核对象,可是当进程终止执行时,系统能确保全部内容均被正确地清除。另外,这个情况是用于全部对象,资源和内存块,也就是说,当进程终止时,系统将保证不会留下不论什么对象。)

TerminateThread()

函数的声明例如以下:

BOOL TerminateThread( HANDLE hThread, DWORD dwExitCode);

作用:

在线程外终止一个线程,用于强制终止线程。

參数说明:

HANDLE htread:被终止的线程的句柄,为CWinThread指针。

DWORD dwExitCode:退出码。

返回值:

函数运行成功则返回非零值,运行失败返回0。调用getlasterror获得返回的值。

听过无数次不要TerminateThread,仅仅是工作中经常使用,貌似也没有什么问题。今天在高强度測试中发现了一个不可原谅的错误。參看以下的样例

DWORD __stdcall mythread(void*)  
{  
    while( true )  
    {  
        char* p = new char[1024];  
  
        delete [] p;  
    }  
}  
  
int _tmain(int argc, _TCHAR* argv[])  
{  
  
    HANDLE h = CreateThread(NULL, 0, mythread, NULL, 0, NULL);  
  
    Sleep(1000);  
  
    TerminateThread(h , 0);  
    h = NULL;  
  
    char* p = new char[1024]; // 这里会死锁, 过不去  
  
    delete [] p;  
  
    return 0;  
}

为什么死锁呢?new操作符用的是小块堆,整个进程在分配和回收内存时,都要用同一把锁。假设一个线程在占用该锁时被杀死(即临死前该线程在new或delete操作中),其它线程就无法再使用new或delete了,表现为hang住。

<核心编程>里明白提醒不要TerminateThread,但原因并非血淋淋滴。今天发现的这个bug印证了此书的价值。

另注:很多暂时的网络操作经经常使用TerminateThread,作为网络不通时的退出机制,以后要改改了。比方让该线程自生自灭,自行退出。

ExitThread是推荐使用的结束一个线程的方法,当调用该函数时,当前线程的栈被释放,然后线程终止,相对于TerminateThread函数来说,这样做可以更好地完毕附加在该线程上的DLL的清除工作

终止线程两个函数:ExitThread() 和 TerminateThread()



若要终止线程的执行,能够使用以下四种的方法:

线程函数退出循环来返回   (最佳方法 )。

通过调用ExitThread 函数,线程将自行撤消(尽量不要使用这样的方法 )。

同一个进程或还有一个进程中的线程调用TerminateThread 函数(最好避免使用这样的方法 )。

该线程的主进程终止执行(避免使用 )。

以下将介绍终止线程执行的方法,而且说明线程终止执行时会出现什么情况。

1.线程函数返回

始终都应该将线程设计成这种形式,即当想要线程终止执行时,它们就行返回。这是

确保全部线程资源被正确地清除的唯一办法。

假设线程可以返回,就行确保下列事项的实现:

a) 在线程函数中创建的全部C + +对象均将通过它们的撤消函数正确地撤消。

b)操作系统将正确地释放线程堆栈使用的内存。

c)系统将线程的退出代码(在线程的内核对象中维护)设置为线程函数的返回值。

d)系统将递减线程内核对象的使用计数。

2.ExitThread 函数

能够让线程调用ExitThread 函数,以便强制线程终止执行:

该函数将终止线程的执行,并导致操作系统清除该线程使用的全部操作系统资源。可是,C++资源(如C++类对象)将不被撤消。因为这个原因,最好从线程函数返回,而不是通过调用ExitThread 来返回。

当然,能够使用ExitThread  的dwExitThread 參数告诉系统将线程的退出代码设置为什么。ExitThread 函数并不返回不论什么值,由于线程已经终止执行,不能执行很多其它的代码。

注意终止线程执行的最佳方法是让它的线程函数返回。可是,假设使用本节介绍的方法,应该知道ExitThread 函数是Windows用来撤消线程的函数。假设编写C/C++代码,那么决不应该调用ExitThread 。应该使用Visual C++执行期库函数_endthreadex。假设不使用Microsoft的Visual C++编译器,你的编译器供应商有它自己的ExitThread 的替代函数。无论这个替代函数是什么,都必须使用。本章后面将说明_endthreadex的作用和它的重要性。

3.TerminateThread 函数

调用TerminateThread 函数也可以终止线程的执行:

与ExitThread 不同,ExitThread 总是撤消调用的线程,而TerminateThread 可以撤消不论什么线程。hThread參数用于标识被终止执行的线程的句柄。当线程终止执行时,它的退出代码成为你作为dwExitThread 參数传递的值。同一时候,线程的内核对象的使用计数也被递减。

注意TerminateThread 函数是异步执行的函数,也就是说,它告诉系统你想要线程终止执行,可是,当函数返回时,不能保证线程被撤消。假设须要确切地知道该线程已经终止执行,必须调用WaitForSingleObject或者类似的函数,传递线程的句柄。

设计良好的应用程序从来不使用这个函数,由于被终止执行的线程收不到它被撤消的通知。线程不能正确地清除,而且不能防止自己被撤消。注意当使用返回或调用ExitThread 的方法撤消线程时,该线程的内存堆栈也被撤消。可是,假设使用TerminateThread ,那么在拥有线程的进程终止执行之前,系统不撤消该线程的堆栈。Microsoft有益用这样的方法来实现TerminateThread 。假设其它仍然正在执行的线程要引用强制撤消的线程堆栈上的值,那么其它的线程就会出现訪问违规的问题。假设将已经撤消的线程的堆栈留在内存中,那么其它线程就能够继续非常好地执行。此外,当线程终止执行时,
DLL通常接收通知。假设使用Terminate Thread 强迫线程终止,DLL就不接收通知,这能阻止适当的清除(具体信息參见第20章)。

4.在进程终止执行时撤消线程

ExitProcess和TerminateProcess函数也能够用来终止线程的执行。区别在于这些线程将会使终止执行的进程中的全部线程全部终止执行。另外,因为整个进程已经被关闭,进程使用的全部资源肯定已被清除。这当然包含全部线程的堆栈。这两个函数会导致进程中的剩余线程被强制撤消,就像从每一个剩余的线程调用TerminateThread 一样。显然,这意味着正确的应用程序清除没有发生,即C++对象撤消函数没有被调用,数据没有转至磁盘等等。

CloseHandle(),TerminateThread(),ExitThread()的差别的更多相关文章

  1. CloseHandle(),TerminateThread(),ExitThread()的区别

    线程的handle用处:线程的handle是指向“线程的内核对象”的,而不是指向线程本身.每个内核对象只是内核分配的一个内存块,并且只能由内核访问.该内存块是一种数据结构,它的成员负责维护对象的各种信 ...

  2. C++windows内核编程笔记day13 进程、线程与信号量

    Windows进程 进程是一个容器,包括程序运行须要的代码.数据.资源等信息, windows进程的特点: 每一个进程都有自己的ID号 每一个进程都有自己的地址空间.进程之间无法訪问对方的地址空间. ...

  3. 转:Delphi中使用比较少的一些语法

    http://www.cnblogs.com/Murphieston/p/5577836.html 本文是为了加强记忆而写,这里写的大多数内容都是在编程的日常工作中使用频率不高的东西,但是又十分重要. ...

  4. [16]Windows内核情景分析 --- 服务管理

    随时可以看到任务管理器中有一个services.exe进程,这个就是系统的服务控制管理进程,简称SCM 这个进程专门用来管理服务(启动.停止.删除.配置等操作) 系统中所有注册的服务都登记在\HKEY ...

  5. CloseHandle()函数的使用

    CloseHandle()函数的使用?? 很多程序在创建线程都这样写的:............ThreadHandle = CreateThread(NULL,0,.....);CloseHande ...

  6. CWinThread类,使用后要不要使用CloseHandle释放内核

    在VC++中用AfxBeginThread()开启线程的时候,返回的是CWinThead类的指针.但是使用后是否应该用CloseHandle释放内核资源呢? 在<Windows核心编程>中 ...

  7. 线程创建后为什么要调用CloseHandle

    很多程序在创建线程都这样写的: ............ ThreadHandle = CreateThread(NULL,0,.....); CloseHandel(ThreadHandle );  ...

  8. ROLAP和MOLAP的概念和差别

    ROLAP和MOLAP的概念和差别OLAP(on-Line Analysis Processing)是使分析人员.管理人员或执行人员能够从多角度对信息进行快速.一致.交互地存取,从而获得对数据的更深入 ...

  9. apt-get upgarde和dist-upgrade的差别

    apt-get upgarde和dist-upgrade的差别 apt-get upgarde和dist-upgrade的差别   Debian/Ubuntu Linux都使用apt,升级时都是:  ...

随机推荐

  1. 我的CSS架构

    写在前面 都是自己看别人的架构,自己积累下来的一些东西,这里只是阐述自己的一些观念.借此希望同行交流交流下看法,共勉. 不同架构的CSS 业务流程不同,团队配员不同.会有各种各样的CSS架构. 有的会 ...

  2. 基于visual Studio2013解决C语言竞赛题之0704字符串长度

     题目

  3. [Boost]boost的时间和日期处理-(1)日期的操作

    <开篇> Boost.DateTime库提供了时间日期相关的计算.格式化.转换.输入输出等等功能,为C++的编程提供了便利.不过它有如下特点: 1. Boost.DateTime 只支持1 ...

  4. Codeforces 468D Tree

    题目 给出一棵带边权的树,求一个排列\(p\),使得\(\sum_{i=1}^{n}{dis(i, p_i)}\)的值最大,其中\(dis(v, u)\)表示\(v\)到\(u\)的距离. 算法 这题 ...

  5. Android圆环形颜色选择器:HoloColorPicker

    HoloColorPicker实现圆环形颜色选择器,可以改变颜色饱和度来选择颜色.选择颜色时,可以用手指沿着圆环滑动一个滑块,从而选择颜色. 添加以下XML至你的布局中: ? 1 2 3 4 < ...

  6. WebStorm开发Nodejs环境搭建,包括破解最新的WebStom11破解

    先放上链接:http://pan.baidu.com/s/1eQUJZGm 文件内包含注册码和WebStom11安装包,希望能够帮助到大家,少些周折

  7. boost.xml_parser中文字符问题

    当使用xml_parser进行读xml时,如果遇到中文字符会出现解析错误. 网上有解决方案说使用wptree来实现,但当使用wptree来写xml时也会出错.而使用ptree来写中文时不会出错. 综合 ...

  8. Swift - 使用CATransition制作过渡动画(页面切换转场效果)

    CATransition动画主要在过渡时使用,比如两个页面层级改变的时候添加一个转场效果.CATransition分为两类,一类是公开的动画效果,一类是非公开的动画效果. 1,公开动画效果: kCAT ...

  9. java基本数据类型转换成byte[]数组

    import java.io.UnsupportedEncodingException;  public class ConToByte {      /**     * double转换byte   ...

  10. 浅析js的执行顺序

    javascript是一种描述型的脚本语言,是一种解析语言,由浏览器动态解析,不同种类的浏览器不同版本的浏览器对于js的解析有着微小的差别,不同浏览器的js解析引擎效率也有高低,下面来给大家分析一下j ...