没有搞懂老帖子,关于WaitforsingleObject

baitiane7100 2012-04-25 08:43:42



老帖子没有搞懂,关于WaitforSingleObject

waitforsingleObject(句柄,-1); 表示 当 句柄所指的东东有信号的时候,才会返回。。。。。

这句话是来自windows核心编程上的。 这里的句柄是表示线程内核。不是Event.


fun1Proc的代码可以看出,首先进入临界区,然后开始执行。。。。

fun2Proc同理。

但是事实上,线程根本没有运行!! 没有打印任何结果。 不少网友认为之所以没有执行线程,
是因为CloseHandle和WaitforSingleObject顺序反了,颠倒过来,就可以了。。。

别忘了,CreateThread 后,线程的内核对象是2,不是1,所以可以创建后,就CloseHandle.

所以 颠倒顺序,没有说到点上。





int tickets = 100;

CRITICAL_SECTION criSection;
int main()
{
HANDLE hThread2;
HANDLE hThread1;

InitializeCriticalSection(&criSection);

hThread1 = CreateThread(NULL,0,Fun1Proc1,NULL,0,NULL);
hThread2 = CreateThread(NULL,0,Fun1Proc2,NULL,0,NULL);

CloseHandle(hThread1);
CloseHandle(hThread2);



WaitForSingleObject(hThread1,-1);
WaitForSingleObject(hThread2,-1);

DeleteCriticalSection(&criSection);
return 0 ;
}




DWORD WINAPI Fun1Proc1(
LPVOID lpParameter // thread data
)
{
while(TRUE)
{
EnterCriticalSection(&criSection);
if(tickets>0)
{
Sleep(1);
cout<<"thread1 sell ticket : "<<tickets--<<endl;
}
else{
LeaveCriticalSection(&criSection);
break;
}
LeaveCriticalSection(&criSection);

}
return 0;
}

DWORD WINAPI Fun1Proc2(
LPVOID lpParameter // thread data
)
{
while(TRUE)
{
EnterCriticalSection(&criSection);
if(tickets>0)
{
Sleep(1);
cout<<"thread2 sell ticket : "<<tickets--<<endl;
}
else {
LeaveCriticalSection(&criSection);
break;
}
LeaveCriticalSection(&criSection);
}
return 0;
}

...全文
306 17 打赏 收藏 转发到动态 举报
AI 作业
写回复
用AI写文章
17 条回复
切换为时间正序
请发表友善的回复…
发表回复
baitiane7100 2012-04-26
  • 打赏
  • 举报
回复


hThread3=(HANDLE)_beginthreadex(NULL,0,Fun3Proc,NULL,0,NULL);

WaitForSingleObject(hThread3,-1);


一旦设置为-1, 线程是无法退出的。。。不对吧




[Quote=引用 12 楼 的回复:]

再就是WaitForSingleObject等待时间设置为0,则无论内核对象有无信号,都马上结束等待。
建议设置成INFINITE
[/Quote]
baitiane7100 2012-04-26
  • 打赏
  • 举报
回复





你提到:线程和进程内核对象在创建以后使用计数是2,只有使用计数为0时,内核对象才被系统释放。线程和进程内核对象的只有实用计数为0时才是有信号状态。


这里的内核对象不是 事件内核,是线程内核或进程内核。 创建的时候,是没有信号的,那么

waitforsingleObject(句柄,时间);

这个函数,如果时间到,线程没有结束,返回来的值是超市。

如果时间到, 线程结束了, 返回来又是什么???? 是wait_object_0 ???

如果是的话,那么 就和你说的 冲突了,wait_object_0 表示有信号,对吧,

wait_for_single_0往往用来检测 事件对象是否有信号。。。






[Quote=引用 11 楼 的回复:]

线程和进程内核对象在创建以后使用计数是2,只有使用计数为0时,内核对象才被系统释放。线程和进程内核对象的只有实用计数为0时才是有信号状态。
[/Quote]
GPoint 2012-04-26
  • 打赏
  • 举报
回复
再就是WaitForSingleObject等待时间设置为0,则无论内核对象有无信号,都马上结束等待。
建议设置成INFINITE
GPoint 2012-04-26
  • 打赏
  • 举报
回复
线程和进程内核对象在创建以后使用计数是2,只有使用计数为0时,内核对象才被系统释放。线程和进程内核对象的只有实用计数为0时才是有信号状态。
向立天 2012-04-26
  • 打赏
  • 举报
回复
[Quote=引用 8 楼 的回复:]
再提供一个问题, 这个问了哈几个人,都没有解决


hThread1 = CreateThread(NULL,0,Fun3Proc,NULL,0,NULL);

DWORD val=WaitForSingleObject(hThread1,0); //你看,时间是0,立即返回,超时难道表示线程没有结束???

cout<<val<<endl; //打印258出来,查了,是表示超时……
[/Quote]
你设置是0立即返回是正常的
超市也是正常的
线程总要有执行时间的
richerg85 2012-04-26
  • 打赏
  • 举报
回复
#include <iostream>
#include <windows.h>

using namespace std;

DWORD WINAPI Fun1Proc1(
LPVOID lpParameter // thread data
);
DWORD WINAPI Fun1Proc2(
LPVOID lpParameter // thread data
);

int tickets = 100;

CRITICAL_SECTION criSection;

int main()
{
HANDLE hThread2;
HANDLE hThread1;

InitializeCriticalSection(&criSection);

hThread1 = CreateThread(NULL,0,Fun1Proc1,NULL,0,NULL);
hThread2 = CreateThread(NULL,0,Fun1Proc2,NULL,0,NULL);
Sleep(1000);
CloseHandle(hThread1);
CloseHandle(hThread2);



WaitForSingleObject(hThread1,-1);
WaitForSingleObject(hThread2,-1);

DeleteCriticalSection(&criSection);
return 0 ;
}




DWORD WINAPI Fun1Proc1(
LPVOID lpParameter // thread data
)
{
while(TRUE)
{
EnterCriticalSection(&criSection);
if(tickets>0)
{
Sleep(1);
cout<<"thread1 sell ticket : "<<tickets--<<endl;
}
else{
LeaveCriticalSection(&criSection);
break;
}
LeaveCriticalSection(&criSection);

}
return 0;
}

DWORD WINAPI Fun1Proc2(
LPVOID lpParameter // thread data
)
{
while(TRUE)
{
EnterCriticalSection(&criSection);
if(tickets>0)
{
Sleep(1);
cout<<"thread2 sell ticket : "<<tickets--<<endl;
}
else {
LeaveCriticalSection(&criSection);
break;
}
LeaveCriticalSection(&criSection);
}
return 0;
}


加上Sleep就ok了
richerg85 2012-04-26
  • 打赏
  • 举报
回复
看这篇文章吧,你会得到你要的答案的:
http://blog.csdn.net/richerg85/article/details/7354154
http://blog.csdn.net/richerg85/article/details/7471426

你的这个线程没有执行的原因,应该是主线程没有给新建线程执行时间,所以,需要sleep一下主线程,这样,子线程才有执行的机会。
baitiane7100 2012-04-26
  • 打赏
  • 举报
回复
fangchao918628 2012-04-25
  • 打赏
  • 举报
回复
你设置为0 WaitForSingleObject会立即返回
WaitForSingleObject函数具体形式是这样的,
WaitForSingleObject(HANDLE hObj,DWORD dwMillSec);
第二线程表示它最多等待的时间,即使内核对象没有被触发,当时间到达后一样会结束等待.....
baitiane7100 2012-04-25
  • 打赏
  • 举报
回复
再提供一个问题, 这个问了哈几个人,都没有解决


hThread1 = CreateThread(NULL,0,Fun3Proc,NULL,0,NULL);

DWORD val=WaitForSingleObject(hThread1,0); //你看,时间是0,立即返回,超时难道表示线程没有结束???

cout<<val<<endl; //打印258出来,查了,是表示超时的意思
baitiane7100 2012-04-25
  • 打赏
  • 举报
回复
回复3,5 楼

CloseHandle(hThread2);


WaitForSingleObject(hThread1,-1);
WaitForSingleObject(hThread2,-1);


DWORD val=GetLastError();

cout<<val<<endl;

Sleep(5000);

DeleteCriticalSection(&criSection);


确实是无效句柄,输出是6



[Quote=引用 5 楼 的回复:]

你调试一下看看WaitForSingleObject的返回值不就清楚了
[/Quote]
stjay 2012-04-25
  • 打赏
  • 举报
回复
[Quote=引用 2 楼 的回复:]

晕,不是说了嘛,创建之后, 线程内核对象是2,所以可以理解关闭句柄

引用 1 楼 的回复:

closehandle后句柄就是无效的,必须放wait后面
[/Quote]

进程是有个句柄表的,CloseHandle除了使内核对象引用计数减1,还会把该句柄从句柄表移除
后面再使用该句柄时,会搜索句柄表,没找到,这时就是无效句柄了
向立天 2012-04-25
  • 打赏
  • 举报
回复
你调试一下看看WaitForSingleObject的返回值不就清楚了
swent 2012-04-25
  • 打赏
  • 举报
回复
WaitForSingleObject(hThread1,-1);
GetLastError()返回 ERROR_INVALID_HANDLE,说明CloseHandle使句柄无效,内核对象数递减。WaitForSingleObject失败。程序没有等待就返回,并执行DeleteCriticalSection,此时,critical section object被释放,如果线程还引用criSection会出现错误。线程可能还没执行到cout程序被退出。试试在WaitForSingleObject,后面加上Sleep(5000).
Eleven 2012-04-25
  • 打赏
  • 举报
回复
线程没有机会执行主要原因是主线程结束,整个进程就退出了,你可以再主线程里Sleep一下。
你在WaitForSingleObject之前CloseHandle()关闭窗口句柄,WaitFor函数调用应该失败,错误应该是句柄无效。所以主线程很快就执行结束,子线程就夭折了。。。
baitiane7100 2012-04-25
  • 打赏
  • 举报
回复
晕,不是说了嘛,创建之后, 线程内核对象是2,所以可以理解关闭句柄

[Quote=引用 1 楼 的回复:]

closehandle后句柄就是无效的,必须放wait后面
[/Quote]
genio 2012-04-25
  • 打赏
  • 举报
回复
closehandle后句柄就是无效的,必须放wait后面

15,473

社区成员

发帖
与我相关
我的任务
社区描述
VC/MFC 进程/线程/DLL
社区管理员
  • 进程/线程/DLL社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧