最近在学习的时候 需要创建多线程的应用程序来访问设备 但是不知道为什么始终进不了线程的执行函数里边 经过一番百度 知道了原因 写下以下总结

在学习线程的时候书上有这么一段话“线程对象也可以提前释放,对于大部分的句柄来说,使用CloseHandle函数关闭句柄意味着整个对象被释放,但对于线程句柄来说,关闭它仅释放线程的统计信息,并不会终止线程的执行,如果不在需要使用线程句柄的话,在调用CreateThread后马上就可以将它关闭掉,线程的执行并不会受影响”

以下是一段测试代码:

;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
                .386
                .model        flat,stdcall
                option        casemap:none
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
include            windows.inc
include            kernel32.inc
includelib        kernel32.lib
include            user32.inc
includelib        user32.lib

;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>        
                .data?
hStdOut                dd        ?
hThread                dd        ?

.const

szShow                db        '进入了线程执行函数',0dh,0ah,0
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
                .code
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>        
_Thread         proc        uses ebx esi edi,_lParam
                
                invoke      lstrlen,offset szShow
                push        ecx
                invoke      WriteConsole,hStdOut,offset szShow,eax,esp,NULL
                pop          ecx
                ret

_Thread         endp

;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
start:
                invoke     GetStdHandle,STD_OUTPUT_HANDLE        
                mov         hStdOut,eax
                push       ecx
                invoke     CreateThread,NULL,0,offset _Thread,NULL,0,esp
                pop         ecx
                mov         hThread,eax
                invoke     CloseHandle,hThread
                invoke     WaitForSingleObject,hThread,INFINITE;

invoke     ExitProcess,NULL
;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
                end        start

在上面的代码中,创建完线程以后,就把线程句柄关闭了 但是并没有像预期的那样打印出“进入了线程执行函数” 是没有进入_Thread吗? 还是其他什么原因了

用OllyDBG跟入发现

第一 在_Thread中设置了断点 但是没有断下来就结束了

第二 WaitForSingleObject函数返回失败

百度以后发现一下内容

1. 对于内核对象,系统会维护一个引用计数,
2. 对于每个进程,进程本身维护了一个句柄表,记录它可以操作的内核对象在本进程内的映射值(就是句柄)
3. CloseHandle会删除内核对象的一个引用计数,同时会删除进程句柄表中的一项(如果该句柄在进程内再无引用)
4. WaitForSingleObject对传进来的句柄首先执行的动作就是查进程的句柄表,如果不存在这一项,返回无效句柄错误

WaitForSingleObject在CloseHandle前调用,这个使用hThread还在进程句柄表里
CloseHandle先一步把进程句柄表里的hThread这一项删掉了,再去WaitForSingleObject当然找不到句柄了

修改上边的程序 把WaitForSingleObject放在CloseHandle前执行

......

invoke     WaitForSingleObject,hThread,INFINITE;

invoke     CloseHandle,hThread

......

程序打印出了 期待的“进入了线程执行函数”

由此可以总结 以后在使用CloseHandle关闭线程句柄时 要确认是否后边还要用到它 是否查询进程的句柄表

线程的CloseHandle和WaitForSingleObject相关推荐

  1. wince -- 线程中SetEvent及WaitForSingleObject用法

    设置事件的状态为有标记,释放任意等待线程.如果事件是手工的,此事件将保持有标记直到调用ResetEvent.这种情况下将释放多个线程,如果事件是自动的,此事件将保持有标记,直到一个线程被释放,系统将设 ...

  2. MFC 多线程及线程同步

    一.MFC对多线程编程的支持 MFC中有两类线程,分别称之为工作者线程和用户界面线程.二者的主要区别在于工作者线程没有消息循环,而用户界面线程有自己的消息队列和消息循环. 工作者线程没有消息机制,通常 ...

  3. VC++中线程同步技术分析3

    管理事件内核对象 在前面讲述线程通信时曾使用过事件内核对象来进行线程间的通信,除此之外,事件内核对象也可以通过通知操作的方式来保持线程的同步.对于前面那段使用临界区保持线程同步的代码可用事件对象的线程 ...

  4. 线程同步机制有临界区、互斥、信号量优缺点

    线程同步技术. 1. Critical Sections(临界段),源代码中如果有不能由两个或两个以上线程同时执行的部分,可以用临界段来使这部分的代码执行串行化.它只能在一个独立的进程或一个独立的应用 ...

  5. Visual C++线程同步技术

    线程同步的方式有: 临界区 管理事件内核对象 信号量内核对象 互斥内核对象 分别介绍如下: 使线程同步 在程序中使用多线程时,一般很少有多个线程能在其生命期内进行完全独立的操作.更多的情况是一些线程进 ...

  6. 【详解】消息队列和线程关系

    1.进程-线程-消息队列 简单的来说,什么是进程?什么是线程?打个比方,你的程序要执行,操作系统就会把你的exe文件加载到内存中,那就生成一个进程了(当然还包含分配到的资源等):对于线程,你可以理解成 ...

  7. 如何正确的关闭 MFC 线程

    前言: 近日在网上看到很多人问及如何关闭一下线程,但是我看网上给出的并不详细,而且有些方法还是错误的.小弟在此拙作一篇,不谈别的,只谈及如何正确的关闭MFC的线程,至于Win32和C RunTime的 ...

  8. 经典线程同步 事件Event

    Event 内核对象,实际上是解决线程同步问题的利器. 介绍下函数应用: 第一个 CreateEvent 函数功能:创建事件 函数原型: HANDLECreateEvent( LPSECURITY_A ...

  9. java 线程亲缘性_第7章 线程调度、优先级和亲缘性(1)

    7.1线程的挂起和恢复 (1)线程挂起 ①创建时(如CreateProcess.CreateThread),传入CREATE_SUSPENDED标志 ②用SuspendThread挂起线程.这个函数可 ...

最新文章

  1. [C# 网络编程系列]专题四:自定义Web浏览器
  2. PMCAFF“音乐+社交”产品马拉松大赛圆满结束,10支队伍大放异彩
  3. leetcode 911. Online Election | 911. 在线选举(加强堆 + 二分查找)
  4. scss百分号操作符的一个使用例子
  5. 图解,C语言希尔排序
  6. Eureka缓存机制
  7. HTML判断如果并且,将html转换为js,并且其中含有判断语句
  8. 今天小暑是什么时间_来自小暑的问候,小暑黄鳝赛人参,这5种民俗食物别错过...
  9. Oracle odi 数据表导出到文件
  10. Android开机画面显示
  11. 2022金属非金属矿山(露天矿山)安全管理人员考试练习题模拟考试平台操作
  12. Codeforces 1006A
  13. 管理部门使用计算机属于固定资产核算吗,固定资产核算管理内容
  14. 利用Python解决掉谷歌人机验证,全自动识别真的牛啊
  15. Verilog实现序列信号发生器
  16. 微信登录界面的那个男孩,他每天影响着11.51亿人
  17. MQTT协议快速了解
  18. 手机信号弱或服务器维护,只需几步,即可解决手机信号弱的问题
  19. CIE LAB色差公式与 CIE DE 2000色差公式计算类
  20. 手游SDK相关业务知识

热门文章

  1. shell按长度排序
  2. Java中ThreadPoolExecutor的参数理解
  3. 13款经典JavaScript图形和图表绘制工具
  4. 数据结构——马踏棋盘题解(贪心算法)
  5. 克隆指定的分支:git clone -b 分支名仓库地址
  6. SEO优化:网站优化的五大步骤
  7. 一条龙奇迹私服WEB系统后门及bug
  8. moss管理中心崩溃之解决
  9. svn的更新、合并、提交
  10. couchdb 任意命令执行漏洞(cve-2017-12636)