线程创建后为什么要调用CloseHandle
很多程序在创建线程都这样写的:
............
ThreadHandle = CreateThread(NULL,0,.....);
CloseHandel(ThreadHandle );
。。。。。
这不是刚好创建又关闭了吗?线程怎么运行呢?
================================================
Closing a thread handle does not terminate the associated thread. To remove a thread object, you must terminate the thread, then close all handles to the thread.
================================================
1,线程和线程句柄(Handle)不是一个东西,线程是在cpu上运行的.....(说不清楚了),线程句柄是一个内核对象。我们可以通过句柄来操作线程,但是线程的生命周期和线程句柄的生命周期不一样的。线程的生命周期就是线程函数从开始执行到return,线程句柄的生命周期是从CreateThread返回到你CloseHandle()。
2,所有的内核对象(包括线程Handle)都是系统资源,用了要还的,也就是说用完后一定要closehandle关闭之,如果不这么做,你系统的句柄资源很快就用光了。
3,如果你CreateThread以后需要对这个线程做一些操作,比如改变优先级,被其他线程等待,强制TermateThread等,就要保存这个句柄,使用完了在CloseHandle。如果你开了一个线程,而不需要对它进行如何干预,CreateThread后直接CloseHandle就行了。
所以
CloseHandel(ThreadHandle );
只是关闭了一个线程句柄对象,表示我不再使用该句柄,即不对这个句柄对应的线程做任何干预了。并没有结束线程。
如果你觉得多了一个变量,也可以写为:
CloseHandel(CreateThread(NULL,0,.....));
================================================================
《windows核心编程》上说调用closehandle(HANDLE)表示创建者放弃对该内核对象的操作。如果该对象的引用对象记数为0就撤消该对象。
====================================================================
在线程创建后马上调用CloseHandle()是个良好的做法,这里不会影响线程的执行,就是因为即使你close了这个handle,它的内部记数也不为零. 但如果你不关,在线程结束后,那个线程对象将滞留于内存中,也就是说你有handle leak.
返回这个handle给你,是让你有机会对这个线程实施外部动作,诸如waitforsingleobject之类.
==================================================================
CloseHandle的功能是关闭一个打开的对象句柄,该对象句柄可以是线程句柄,也可以是进程、信号量等其他内核对象的句柄,而ExitThread的功能是终止一个线程,它所接受的参数是一个线程的退出码。
通过调用CloseHandle可以告知系统,已经完成了对某一内核对象的操作,该函数首先检查调用进程的句柄表,来确认进程是否对该句柄所指向的对象有访问权,如果句柄无效则返回FALSE,如果有效,系统将得到该内核对象的数据结构的地址,把结构中的使用计数成员减1,如果计数变为0,则将从内核中释放该内核对象。
如果计数还未到0,就意味着还有其他的进程在使用这个内核对象,那么它就不会被释放。
ExitThread是推荐使用的结束一个线程的方法,当调用该函数时,当前线程的栈被释放,然后线程终止,相对于TerminateThread函数来说,这样做能够更好地完成附加在该线程上的DLL的清除工作。
如果需要进一步的信息,您可以参看:
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/sysinfo/handobj_289x.asp
和http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dllproc/prothred_531g.asp
等有关的MSDN信息。
==================================================================
线程作为一种资源创建后不只被创建线程引用,我想系统自身为了管理线程也会有一个引用,所以用户线程释放线程句柄后,引用计数也不会是零。引用计数是资源自我管理的一种机制,资源本身以引用计数为零来得知别人不再需要自己,从而把自己kill掉。
=================================================================
CreateThread后那个线程的引用计数不是1,调用CloseHandle只是说自己对这个线程没有兴趣了,线程还是正常运行的
=================================================================
CreateThread后那个线程的引用计数不是1,而是2。
creating a new process causes the system to create a process kernel object
and a thread kernel object. At creation time, the system gives each object
an initial usage count of 1. Then, just before CreateProcess returns, the
function opens the process object and the thread object and places the
process-relative handles for each in the hProcess and hThread members of
the PROCESS_INFORMATION structure. When CreateProcess opens these objects
internally, the usage count for each becomes 2.
=================================================================
创建新的进程后,记数初始化为1,而函数需要返回进程内核对象的句柄,相当于打开一次新创建的类核对象,记数再加1
------------------------------------
CloseHandle函数
BOOL CloseHandle(
HANDLE hObject
);
参数
hObject :代表一个已打开对象handle。
返回值
TRUE:执行成功;
FALSE:执行失败,可以调用GetLastError()获知失败原因。
函数说明:
关闭一个内核对象。其中包括文件、文件映射、进程、线程、安全和同步对象等。在CreateThread成功之后会返回一个hThread的handle,且内核对象的计数加1,CloseHandle之后,引用计数减1,当变为0时,系统删除内核对象。
若在线程执行完之后,没有调用CloseHandle,在进程执行期间,将会造成内核对象的泄露,相当于句柄泄露,但不同于内存泄露,这势必会对系统的效率带来一定程度上的负面影响。但当进程结束退出后,系统会自动清理这些资源。
- HANDLE hThread1;
- hThread1 = CreateThread(NULL, 0, Fun1Proc, NULL, 0, NULL);
- WaitForSingleObject(hThread1, INFINITE);
WaitForSingleObject的作用就是等待线程自动结束,继续执行后面的程序
- HANDLE hThread1;
- hThread1 = CreateThread(NULL, 0, Fun1Proc, NULL, 0, NULL);
- CloseHandle(hThread1);
- WaitForSingleObject(hThread1, INFINITE);
原来是CloseHandle之后,WaitForSingleObject得不到thread的句柄,没法再等到这个thread结束
线程创建后为什么要调用CloseHandle的更多相关文章
- Linux线程-创建
Linux的线程实现是在内核以外来实现的,内核本身并不提供线程创建.但是内核为提供线程[也就是轻量级进程]提供了两个系统调用__clone()和fork (),这两个系统调用都为准备一些参数,最终都用 ...
- C# 委托高级应用----线程——创建无阻塞的异步调用(二)
了解IAsyncResult 现在我们已经了解,EndInvoke可以给我们提供传出参数与更新后的ref参数:也可以向我们导出异步函数中的异常信息.例如,我们使用BeginInvoke调用了异步函数S ...
- C# 委托高级应用----线程——创建无阻塞的异步调用(一)
前言 本文大部分内容来自于mikeperetz的Asynchronous Method Invocation及本人的一些个人体会所得,希望对你有所帮助.原英文文献可以在codeproject中搜索到. ...
- 谈.Net委托与线程——创建无阻塞的异步调用(二)
了解IAsyncResult 现在我们已经了解,EndInvoke可以给我们提供传出参数与更新后的ref参数:也可以向我们导出异步函数中的异常信息.例如,我们使用BeginInvoke调用了异步函数S ...
- 谈.Net委托与线程——创建无阻塞的异步调用(一)
前言 本文大部分内容来自于mikeperetz的Asynchronous Method Invocation及本人的一些个人体会所得,希望对你有所帮助.原英文文献可以在codeproject中搜索到. ...
- C# WebService中任务处理线程创建子线程后
protected void WriteLog(string message) { lock (lockObject) { var file = System.IO.File.AppendText(& ...
- windows进程/线程创建过程 --- windows操作系统学习
有了之前的对进程和线程对象的学习的铺垫后,我们现在可以开始学习windows下的进程创建过程了,我将尝试着从源代码的层次来分析在windows下创建一个进程都要涉及到哪些步骤,都要涉及到哪些数据结构. ...
- Java基础加强之多线程篇(线程创建与终止、互斥、通信、本地变量)
线程创建与终止 线程创建 Thread类与Runnable接口的关系 public interface Runnable { public abstract void run(); } public ...
- java多线程-线程创建
Java 线程类也是一个 object 类,它的实例都继承自 java.lang.Thread 或其子类. 可以用如下方式用 java 中创建一个线程,执行该线程可以调用该线程的 start()方法: ...
随机推荐
- PHP面试 PHP基础知识 十一(开发环境及相关配置)
开发环境及相关配置 版本控制软件 集中式和分布式 集中式:集中式版本控制工具,版本库集中存放在中央服务器,团队成员里的每个人工作时从中央服务器下载代码,个人修改后再提交到中央服务器 分布式:分布式版本 ...
- mysql定时任务(数据库管理工具and 纯命令行)
1.工具:Navicat 2.通过下列语句l爱查询event是否开启 打开Navicat命令列界面(点击工具可以看到或按F6) 输入下面命令 show variables like '%sche%'; ...
- WinDows应急响应基础
文件排查 开机启动有无异常文件 msconfig 敏感的文件路径 %WINDIR% %WINDIR%\SYSTEM32\ %TEMP% %LOCALAPPDATA% %APPDATA% 用户目录 新建 ...
- linux kill命令
代码 elif [ "$SIGNAL" = 'reload' ]; then kill -USR1 $PID 总结:kill -9 pid 等同于kill -USR9 pid 等同 ...
- 36-python基础-python3-字典与列表的区别
(1)不像列表,字典中的表项是不排序的.名为 spam 的列表中,第一个表项是 spam[0].但字典中没有“第一个”表项. (2)确定两个列表是否相同时,表项的顺序必须相同,但在字典确定两个字典是否 ...
- Java原理领悟-JMM(java内存模型认知)
总线锁.缓存锁.MESI缓存一致性协议.CPU 层面的内存屏障 1.JMM定义: Java Memory Model(java内存模型)是一系列的Java虚拟机平台对开发者提供的多线程环境下的内存可见 ...
- 树莓派上Opencv highgui的问题
错误描述:https://bbs.csdn.net/topics/394616975?page=1#post-409508178 解决方案:直接改系统环境变量 # vim /etc/profile e ...
- C/C++ 吐槽第一期:你最讨厌的C/C++里面的数据类型是什么
C/C++ 这里面讨论的范围包括从以往开始,到现有的所有官方标准,VC扩展,GCC扩展, C语言部分包括C89.C90.C99.C11这些知名的大版本,中间或者之前的比如K&R这种不出名的小版 ...
- 事务管理ACID
事务是由一组SQL语句组成的逻辑处理单元,事务具有以下4个属性,通常简称为事务的ACID属性. ACID是Atomic(原子性) Consistency(一致性) Isolation(隔离性) Dur ...
- testprns printername [printcapname]
描述 此程序是samba套件的一部分. testprns是个非常简单的测试程序,用于检查smbd作为服务提供的打印机名是否合法. 在这里“Valid”的意思就是“在printcap中可以找到该打印机” ...