CreateEvent在多线程中使用(二)

1、简介

 CreateEvent详细参数介绍,请参考CreateEvent函数解析(一)

HANDLECreateEvent(
LPSECURITY_ATTRIBUTESlpEventAttributes,// 安全属性
BOOLbManualReset,// 复位方式
BOOLbInitialState,// 初始状态
LPCTSTRlpName // 对象名称
);

我们常用比较关心的其实是第2、3个参数,另外两个直接设置为NULL即可,下面分别主要介绍第2、3个参数:

1、bManualReset:TRUE,使用ResetEvent()手动重置为无信号状态;FALSE,当一个等待线程被释放时,自动重置状态为无信号状态。

2、bInitialState:指定事件对象的初始状态,当TRUE,初始状态为有信号状态;当FALSE,初始状态为无信号状态。


2、代码实例进行讲解


2.1 第一种情况

bManualReset:TRUE
bInitialState:TRUE

    //使用手动重置为无信号状态,初始化时有信号状态 
    g_hEvent = CreateEvent(NULL, TRUE, TRUE, NULL);

源代码:

#include <process.h>
#include <Windows.h>
#include <iostream>

HANDLE g_hEvent   = NULL;
HANDLE g_hThread1 = NULL;
HANDLE g_hThread2 = NULL;

unsigned _stdcall ThreadProc1(void* lpParam)
{
    std::cout << "ThreadProc1 come in!" << std::endl;
    DWORD rel = WaitForSingleObject(g_hEvent, INFINITE);
    if (WAIT_OBJECT_0 == rel)
    {
        std::cout << "ThreadProc1 get event signal!" << std::endl;
    }
    std::cout << "ThreadProc1 will out!" << std::endl;
    return 0;
}
unsigned _stdcall ThreadProc2(void* lpParam)
{
    std::cout << "ThreadProc2 come in!" << std::endl;
    DWORD rel = WaitForSingleObject(g_hEvent, INFINITE);
    if (WAIT_OBJECT_0 == rel)
    {
        std::cout << "ThreadProc2 get event signal!" << std::endl;
    }
    std::cout << "ThreadProc2 will out!" << std::endl;
    return 0;
}
int main(int argc, char* argv[])
{
    //使用手动重置为无信号状态,初始化时有信号状态 
    g_hEvent = CreateEvent(NULL, TRUE, TRUE, NULL);

    g_hThread1 = (HANDLE)_beginthreadex(NULL, 0, ThreadProc1, NULL, 0, NULL);
    Sleep(100);
    g_hThread2 = (HANDLE)_beginthreadex(NULL, 0, ThreadProc2, NULL, 0, NULL);
    
    if (!g_hThread1 || !g_hThread2)
    {
        std::cout << "Create Thread Failed!" << std::endl;
    }

    Sleep(5000);   //保证上面两个线程都执行完毕。
    return 0;
}

执行结果:



从结果中可以看出,执行完线程1又执行了线程2:

由于g_hEvent = CreateEvent(NULL, TRUE, TRUE, NULL);//使用手动重置为无信号状态,初始化时有信号状态,

所以g_hEvent一直是处于有信号的状态,即线程1释放以后,g_hEvent还是处于有信号状态,所以线程2正常执

行了。要想使g_hEvent没有信号,我们必须手动使用代码ResetEvent(g_hEvent)才可以将其设置为无信号。

2.2 第二种情况

bManualReset:TRUE
bInitialState:TRUE

    //<span class="comment" style="margin: 0px; padding: 0px; border: none; color: rgb(0, 130, 0); font-family: Consolas, 'Courier New', Courier, mono, serif; line-height: 18px;">当一个等待线程被释放时,自动重置为无信号状态,初始是有信号状态</span><span style="margin: 0px; padding: 0px; border: none; font-family: Consolas, 'Courier New', Courier, mono, serif; line-height: 18px;"> </span>
    g_hEvent = CreateEvent(NULL, FALE, TRUE, NULL);

源代码:

#include <process.h>
#include <Windows.h>
#include <iostream>

HANDLE g_hEvent   = NULL;
HANDLE g_hThread1 = NULL;
HANDLE g_hThread2 = NULL;

unsigned _stdcall ThreadProc1(void* lpParam)
{
    std::cout << "ThreadProc1 come in!" << std::endl;
    DWORD rel = WaitForSingleObject(g_hEvent, INFINITE);
    if (WAIT_OBJECT_0 == rel)
    {
        std::cout << "ThreadProc1 get event signal!" << std::endl;
    }
    std::cout << "ThreadProc1 will out!" << std::endl;
    return 0;
}
unsigned _stdcall ThreadProc2(void* lpParam)
{
    std::cout << "ThreadProc2 come in!" << std::endl;
    DWORD rel = WaitForSingleObject(g_hEvent, INFINITE);
    if (WAIT_OBJECT_0 == rel)
    {
        std::cout << "ThreadProc2 get event signal!" << std::endl;
    }
    std::cout << "ThreadProc2 will out!" << std::endl;
    return 0;
}
int main(int argc, char* argv[])
{
    //当一个等待线程被释放时,自动重置为无信号状态,初始是有信号状态 
    g_hEvent = CreateEvent(NULL, FALSE, TRUE, NULL);

    g_hThread1 = (HANDLE)_beginthreadex(NULL, 0, ThreadProc1, NULL, 0, NULL);
    Sleep(100);
    g_hThread2 = (HANDLE)_beginthreadex(NULL, 0, ThreadProc2, NULL, 0, NULL);
    
    if (!g_hThread1 || !g_hThread2)
    {
        std::cout << "Create Thread Failed!" << std::endl;
    }

    Sleep(5000);   //保证上面两个线程都执行完毕。
    return 0;
}


执行结果:

从结果中可以看出,执行完线程1又执行了线程2,线程2没有获得信号执行完:

由于g_hEvent = CreateEvent(NULL, FALE, TRUE, NULL);//当一个等待线程被释放时,自动重置为无信号状态,

初始是有信号状态 ,所以执行线程1的时候g_hEvent是有信号的,当线程1获取信号,线程释放以后,会制动将

g_hEvent设置为无信号状态,所以线程2一直在WaitForSingleObject(hEvent,INFINITE);处无法获取信号,

阻塞不能正常执行完。

2.3 第三种情况

bManualReset:TRUE
bInitialState:FALE

//使用手动重置为无信号状态,初始化时为无信号状态
g_hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);

源代码:

#include <process.h>
#include <Windows.h>
#include <iostream>

HANDLE g_hEvent   = NULL;
HANDLE g_hThread1 = NULL;
HANDLE g_hThread2 = NULL;

unsigned _stdcall ThreadProc1(void* lpParam)
{
    std::cout << "ThreadProc1 come in!" << std::endl;
    DWORD rel = WaitForSingleObject(g_hEvent, INFINITE);
    if (WAIT_OBJECT_0 == rel)
    {
        std::cout << "ThreadProc1 get event signal!" << std::endl;
    }
    std::cout << "ThreadProc1 will out!" << std::endl;
    return 0;
}
unsigned _stdcall ThreadProc2(void* lpParam)
{
    std::cout << "ThreadProc2 come in!" << std::endl;
    DWORD rel = WaitForSingleObject(g_hEvent, INFINITE);
    if (WAIT_OBJECT_0 == rel)
    {
        std::cout << "ThreadProc2 get event signal!" << std::endl;
    }
    std::cout << "ThreadProc2 will out!" << std::endl;
    return 0;
}
int main(int argc, char* argv[])
{
    //使用手动重置为无信号状态,初始化时为无信号状态
    g_hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);

    g_hThread1 = (HANDLE)_beginthreadex(NULL, 0, ThreadProc1, NULL, 0, NULL);
    Sleep(100);
    g_hThread2 = (HANDLE)_beginthreadex(NULL, 0, ThreadProc2, NULL, 0, NULL);
    
    if (!g_hThread1 || !g_hThread2)
    {
        std::cout << "Create Thread Failed!" << std::endl;
    }

    Sleep(10000);   //保证上面两个线程都执行完毕。
    return 0;
}

执行结果可想而知,两个线程都处于等待状态,如下:


因为初始为无信号状态,所以hEvent一直处于无信号状态,因此这两个线程一直在等待,直到主线程结束。

这种情况使用我们可以使用SetEvent(g_hEvnet)将其设置为有信号的状态,线程就可以正常执行了。

2.4 第四种情况

bManualReset: FALSE
bInitialState:FALSE

//线程释放后自动重置为无信号状态,初始化时为无信号状态
g_hEvent = CreateEvent(NULL, FALSE, FALSE, NULL);

源代码:

#include <process.h>
#include <Windows.h>
#include <iostream>

HANDLE g_hEvent   = NULL;
HANDLE g_hThread1 = NULL;
HANDLE g_hThread2 = NULL;

unsigned _stdcall ThreadProc1(void* lpParam)
{
    std::cout << "ThreadProc1 come in!" << std::endl;
    DWORD rel = WaitForSingleObject(g_hEvent, INFINITE);
    if (WAIT_OBJECT_0 == rel)
    {
        std::cout << "ThreadProc1 get event signal!" << std::endl;
    }
    std::cout << "ThreadProc1 will out!" << std::endl;
    return 0;
}
unsigned _stdcall ThreadProc2(void* lpParam)
{
    std::cout << "ThreadProc2 come in!" << std::endl;
    DWORD rel = WaitForSingleObject(g_hEvent, INFINITE);
    if (WAIT_OBJECT_0 == rel)
    {
        std::cout << "ThreadProc2 get event signal!" << std::endl;
    }
    std::cout << "ThreadProc2 will out!" << std::endl;
    return 0;
}
int main(int argc, char* argv[])
{
    //线程释放后自动重置为无信号状态,初始化时为无信号状态
    g_hEvent = CreateEvent(NULL, FALSE, FALSE, NULL);

    if (SetEvent(g_hEvent))
    {
        std::cout << "SetEvent Success!" << std::endl;
    }
    g_hThread1 = (HANDLE)_beginthreadex(NULL, 0, ThreadProc1, NULL, 0, NULL);
    Sleep(100);
    g_hThread2 = (HANDLE)_beginthreadex(NULL, 0, ThreadProc2, NULL, 0, NULL);
    
    if (!g_hThread1 || !g_hThread2)
    {
        std::cout << "Create Thread Failed!" << std::endl;
    }

    Sleep(10000);   //保证上面两个线程都执行完毕。
    return 0;
}

执行结果,如下:


由于调用SetEvent将g_hEvent置为有信号状态,线程1正常执行,又由于调用完线程1后,g_hEvent自动重置

为无信号状态,所以线程2只能处于等待,直到主线程退出。

修改:

线程1中的SetEvent(hEvent);的注释去掉,再运行,则线程1和线程2 都不会执行,以为初始为无信号状态。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值