情况一:HANDLE hThread = NULL;
UINT __stdcall Fun(LPVOID pParam)
{
ASSERT(CloseHandle(hThread));
Sleep(5000);
return 0;
}unsigned int threadID;
hThread = (HANDLE) _beginthreadex(NULL, 0, Fun, NULL, 0, &threadID);
WaitForSingleObject(hThread, INFINITE);
结果是:WaitForSingleObject等待5秒(CloseHandle调用是成功的)情况二:HANDLE hThread = NULL;
UINT __stdcall Fun(LPVOID pParam)
{
Sleep(5000);
return 0;
}unsigned int threadID;
hThread = (HANDLE) _beginthreadex(NULL, 0, Fun, NULL, 0, &threadID);
ASSERT(CloseHandle(hThread));
WaitForSingleObject(hThread, INFINITE);
结果是:WaitForSingleObject不等待(CloseHandle调用是成功的)情况三:HANDLE hThread = NULL;
UINT __stdcall Fun(LPVOID pParam)
{
Sleep(5000);
return 0;
}unsigned int threadID;
hThread = (HANDLE) _beginthreadex(NULL, 0, Fun, NULL, 0, &threadID);
WaitForSingleObject(hThread, INFINITE);
结果是:WaitForSingleObject等待5秒(没有调用CloseHandle)经过上面的测试,我有点发晕了,到底CloseHandle会不会对WaitForSingleObject产生影响,在什么情况下产生影响,产生什么样的影响?
UINT __stdcall Fun(LPVOID pParam)
{
ASSERT(CloseHandle(hThread));
Sleep(5000);
return 0;
}unsigned int threadID;
hThread = (HANDLE) _beginthreadex(NULL, 0, Fun, NULL, 0, &threadID);
WaitForSingleObject(hThread, INFINITE);
结果是:WaitForSingleObject等待5秒(CloseHandle调用是成功的)情况二:HANDLE hThread = NULL;
UINT __stdcall Fun(LPVOID pParam)
{
Sleep(5000);
return 0;
}unsigned int threadID;
hThread = (HANDLE) _beginthreadex(NULL, 0, Fun, NULL, 0, &threadID);
ASSERT(CloseHandle(hThread));
WaitForSingleObject(hThread, INFINITE);
结果是:WaitForSingleObject不等待(CloseHandle调用是成功的)情况三:HANDLE hThread = NULL;
UINT __stdcall Fun(LPVOID pParam)
{
Sleep(5000);
return 0;
}unsigned int threadID;
hThread = (HANDLE) _beginthreadex(NULL, 0, Fun, NULL, 0, &threadID);
WaitForSingleObject(hThread, INFINITE);
结果是:WaitForSingleObject等待5秒(没有调用CloseHandle)经过上面的测试,我有点发晕了,到底CloseHandle会不会对WaitForSingleObject产生影响,在什么情况下产生影响,产生什么样的影响?
解决方案 »
- ON_NOTIFY_RANGE怎么使用?error LNK2001: 无法解析的外部符号 "public: void __thiscall CmycomDlg:
- 数据库编程,ODBC,DAO,OLE DB,ADO,我是该都学呢?还是学一两种,其他了解就可以?该把精力集中到哪上面呢?
- 看看这段毛病在哪?一点开就提示Debug Assertion Failed.
- 请问怎样用SendMessage向一个控件发送VK_RIGHT消息
- 请教:为什么在系统键盘钩子中无法写入数据到全局文件指针?
- 在线程中调用Connect的问题?
- 请大侠帮忙,。。。。。。。。。。。。。急,在线等
- 是不是一定要setevent?
- 谁能帮助我:怎样在OpenGL中显示三维中文字体?
- 获取打文队列文件名时,遇到"本地下层文档"问题,请问如何解决.(附源码)
- 怎么将dll合并到exe文件
- 请教:VC+MapX 鹰眼 添加两个地图窗口 控件问题 !
这种情况 WaitForSingleObject 在 CloseHandle 前调用, WaitForSingleObject 会等待线程结束, CloseHandle 不会影响
情况二
WaitForSingleObject 的Handle被Close, Handle无效, 所以WaitForSingleObject 调用失败, 所以没等待
情况三
一般用法
你说:
情况一
这种情况 WaitForSingleObject 在 CloseHandle 前调用, WaitForSingleObject 会等待线程结束, CloseHandle 不会影响 那如果WaitForSingleObject 在 CloseHandle 之后调用呢?是不是CloseHandle 就会影响到WaitForSingleObject了呢?我将情况一改为如下,可是CloseHandle 仍然影响不了WaitForSingleObject,如下:
HANDLE hThread = NULL;
UINT __stdcall Fun(LPVOID pParam)
{
Sleep(5000);
ASSERT(CloseHandle(hThread));
Sleep(5000);
return 0;
}unsigned int threadID;
hThread = (HANDLE) _beginthreadex(NULL, 0, Fun, NULL, 0, &threadID);
WaitForSingleObject(hThread, INFINITE);
结果是等待了10秒,这又是为什么呢?
而在情况二中:主线程自己调用CloseHandle,再调用WaitForSingleObject,就可以得到一个错误(句柄无效)。
HANDLE hThread = NULL;
UINT __stdcall Fun(LPVOID pParam)
{
Sleep(5000);
ASSERT(CloseHandle(hThread));
Sleep(5000);
return 0;
}unsigned int threadID;
hThread = (HANDLE) _beginthreadex(NULL, 0, Fun, NULL, 0, &threadID);
WaitForSingleObject(hThread, INFINITE);
这样做的目的是在WaitForSingleObject之后调用CloseHandle,可能WaitForSingleObject仍然等待了10秒!即等待到线程结束。
这样 WaitForSingleObject 也在 CloseHandle 前调用, 跟情况一一样你这样试试HANDLE hThread = NULL;
UINT __stdcall Fun(LPVOID pParam)
{
ASSERT(CloseHandle(hThread));
Sleep(15000);
return 0;
}unsigned int threadID;
hThread = (HANDLE) _beginthreadex(NULL, 0, Fun, NULL, 0, &threadID);
Sleep(5000);
WaitForSingleObject(hThread, INFINITE);
这是为什么呢?
系统或程序自身的机制问题, 举个简单的例子CHAR szName[] = "xvsdfd";
CHAR * pStr;pStr = szName; //等效 OpenHandle, 用句柄访问对象
printf("%s", pStr); //使用句柄访问对象,类似WaitForSingleObjectpStr = NULL; //等效 CloseHandlepStr = NULL; 与 printf("%s", pStr); 这俩句前后不一样, 结果就会不一样
下面是window内核编程的原文:系统要创建和操作若干类型的内核对象,比如存取符号对象、事件对象、文件对象、文件映射对象、I/O完成端口对象、作业对象、信箱对象、互斥对象、管道对象、进程对象、信标对象、线程对象和等待计时器对象等。这些对象都是通过调用函数来创建的。例如,CreateFileMapping函数可使系统能够创建一个文件映射对象。每个内核对象只是内核分配的一个内存块,并且只能由该内核访问。该内存块是一种数据结构,它的成员负责维护该对象的各种信息。有些数据成员(如安全性描述符、使用计数等)在所有对象类型中是相同的,但大多数数据成员属于特定的对象类型。例如,进程对象有一个进程ID、一个基本优先级和一个退出代码,而文件对象则、拥有一个字节位移、一个共享模式和一个打开模式。特性:内核对象的使用计数,安全性等。这里我们讨论到的是关于他的使用计数这个特性。内核知道有多少进程正在使用某个内核对象,因为每个对象包含一个使用计数。使用计数是所有内核对象类型常用的数据成员之一。当一个对象刚刚创建时,它的使用计数被置为1。然后,当另一个进程访问一个现有的内核对象时,使用计数就递增1。当进程终止运行时,内核就自动确定该进程仍然打开的所有内核对象的使用计数。如果内核对象的使用计数降为0,内核就撤消该对象。这样可以确保在没有进程引用该对象时系统中不保留任何内核对象。
------------------------------------------
如果在WaitForSingleObject之前CloseHandle了,这样系统会撤销这个对象,这样handle已经失效。所以再wait的话已经是无效的handle了。如果是之后CloseHandle为什么不会有影响呢,因为WaitForSingleObject会使计数+1达到2,CloseHandle只是将这个计数-1而已,这样内核对象计数还有1,这样这个handle还是有效的,所以这时再CloseHandle就还不会有影响。并且的WaitForSingleObject退出的时候也应该会有CloseHandle这样的操作的。这个应该和COM中AddRef和Release这个两个函数非常像。
1. 对于内核对象,系统会维护一个引用计数,
2. 对于每个进程,进程本身维护了一个句柄表,记录它可以操作的内核对象在本进程内的映射值(就是句柄)
3. CloseHandle会删除内核对象的一个引用计数,同时会删除进程句柄表中的一项(如果该句柄在进程内再无引用)
4. WaitForSingleObject对传进来的句柄首先执行的动作就是查进程的句柄表,如果不存在这一项,返回无效句柄错误这样解释应该很清楚了吧
在情况1里WaitForSingleObject在CloseHandle前调用,这个使用hThread还在进程句柄表里
情况2里CloseHandle先一步把进程句柄表里的hThread这一项删掉了,再去WaitForSingleObject当然找不到句柄了