线程中的CloseHandle()函数

本文解释了CloseHandle函数在Windows编程中的作用,说明了它仅用于关闭内核对象句柄,并不会终止线程。文章详细阐述了线程句柄与线程的区别,以及为什么在创建线程后立即关闭句柄是一种好习惯。

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


转载自:http://www.cnblogs.com/cryinstall/archive/2011/08/06/2280830.html

### 线程与操作函数的关系 线程函数是两种不同的概念,尽管它们之间存在一定的关联。以下是关于两者关系及其区别的详细说明: #### 1. 定义上的区别 - **函数**是指一组封装好的指令集合,用于完成特定的任务。它是程序设计中的基本构建单元,在单线程环境中运行时,按照顺序依次执行其内部语句[^1]。 - **线程**则是操作系统提供的一种轻量级进程机制,表示程序的一个独立执行流。多个线程可以共享同一地址空间内的资源(如内存),并行或并发地执行各自的任务。 #### 2. 执行上下文的不同 - 当提到“操作函数”,通常指的是某个具体的功能实现逻辑由一段代码即某函数表达出来。而启动一个新线程,则意味着让这部分功能在一个新的控制路径上异步进行处理而不是阻塞当前主线程继续往下走[^2]。 例如,在Windows API下通过`CreateThread`创建的新线程会指定要调用的目标函数作为入口点;同样地,在POSIX标准下的Linux/Unix平台里也有类似的接口——`pthread_create()`方法来初始化一个新的工作单位—也就是所谓的‘线程’对象,并传入相应的回调函数指针告诉它应该做什么事情[^3]。 因此可以说每个活跃着的线程都需要绑定至少一个实际存在的可执行体(这里就是普通的C/C++风格常规定义出来的子过程),但是反过来讲并非所有的普通成员方法或者全局辅助工具都会自动成为潜在候选者去参与多核计算当中除非特别安排好相关调度策略才行[^4]。 ```c #include <stdio.h> #include <windows.h> DWORD WINAPI ThreadFunction(LPVOID lpParam){ char *message = (char*)lpParam; printf("%s\n", message); return 0; } int main(){ HANDLE hThread1, hThread2; DWORD threadID; hThread1 = CreateThread(NULL, 0, ThreadFunction, "Hello from thread 1!", 0, &threadID); hThread2 = CreateThread(NULL, 0, ThreadFunction, "Hello from thread 2!", 0, NULL); WaitForSingleObject(hThread1, INFINITE); CloseHandle(hThread1); WaitForSingleObject(hThread2, INFINITE); CloseHandle(hThread2); return 0; } ``` 上述示例展示了如何利用 Windows 的 `CreateThread` 来建立两条单独的数据传输线路以便同时显示不同消息串的内容而不互相干扰彼此进度情况。 --- ### 结论 综上所述,虽然在线程启动过程中确实需要用到某些预先编写好的行为描述模块(即那些被当作参数传递进去供后续使用的匿名或有名实体),但从本质上来看这两者的范畴并不相同也不能混淆视之。简单概括如下几点帮助理解记忆: - 函数只是单纯的一段静态源码片段; - 而线程则代表动态变化的状态信息记录载体形式之一种而已!
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值