代码改变世界

WaitForSingleObjec等待Event成功引起的副作用

2012-12-13 18:13  kennyMc  阅读(4270)  评论(0编辑  收藏  举报

一个自动重置事件的对象,WaitForSingleObject在等待成功以后会把事件对象设置为未触发状态(马上调用ResetEvent()函数),而手动设置事件对象不会有这个副作用。

#include <iostream>
#include <process.h>
#include <windows.h>
#include <string>
using std::cout;
using std::endl;
using std::string;

const int num=10;
int count;
HANDLE ThreadEvent;
unsigned __stdcall ThreadFun(void* par);

int main()
{
    //创建内核事件对象(自动重置,未激活状态)
    ThreadEvent=CreateEvent(NULL,FALSE,FALSE,NULL);
    HANDLE handles[num];
    for(int i=0;i<num;++i)
    {
        handles[i]=(HANDLE)_beginthreadex(NULL,0,ThreadFun,NULL,0,0);
        WaitForSingleObject(ThreadEvent,INFINITE);
        //自动激活状态的事件,WaitForSingleObject带来的副作用就是会自己调用ResetEvent()将事件设置为未激活
    }
    for(int i=0;i<num;++i)
        CloseHandle(handles[i]);
    CloseHandle(ThreadEvent);//关闭内核事件对象
    system("PAUSE");
    return 0;
}
unsigned __stdcall ThreadFun(void* par)
{
    cout<<"count:"<<++count<<endl;
    SetEvent(ThreadEvent);//设置事件为激活状态
    return 0;
}

把事件对象设置为手动重置,就需要我们手动重置事件状态。

int main()
{
    //创建内核事件对象(手动重置,未激活状态)
    ThreadEvent=CreateEvent(NULL,TRUE,FALSE,NULL);
    HANDLE handles[num];
    for(int i=0;i<num;++i)
    {
        handles[i]=(HANDLE)_beginthreadex(NULL,0,ThreadFun,NULL,0,0);
        WaitForSingleObject(ThreadEvent,INFINITE);
        //手动激活的事件,WaitForSingleObject不会重置事件为未激活。
        ResetEvent(ThreadEvent);//手动重置事件对象为未激活状态
    }
    for(int i=0;i<num;++i)
        CloseHandle(handles[i]);
    CloseHandle(ThreadEvent);//关闭内核事件对象
    system("PAUSE");
    return 0;
}

上面代码内核事件对象为手动重置,所以在WaitForSingleObject以后需要手动调用ResetEvent(),如果把ResetEvent(ThreadEvent);注释掉,那么所以等待线程都会被触发,导致同步失败。

    for(int i=0;i<num;++i)
    {
        handles[i]=(HANDLE)_beginthreadex(NULL,0,ThreadFun,NULL,0,0);
        WaitForSingleObject(ThreadEvent,INFINITE);
        //手动激活的事件,WaitForSingleObject不会重置事件为未激活。
        //ResetEvent(ThreadEvent);//后面的线程都会很顺利的执行,事件对象一直为激活状态
    }

线程执行同步失败,输出混乱,可以将num变量设置大点,这样更加容易出现混乱输出。

本文版权归kennyMc和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。