C++的CreateEvent

一、事件是很常用的多线程同步互斥机制

函数原型如下所示,一共四个参数:

HANDLE CreateEvent(

 LPSECURITY_ATTRIBUTES lpEventAttributes, // SECURITY_ATTRIBUTES结构指针,可为NULL
 BOOL bManualReset,     // 手动/自动
                                     // TRUE:表示手动,在WaitForSingleObject后必须手动调用ResetEvent清除信号
                                    // FALSE:表示自动,在WaitForSingleObject后,系统自动清除事件信号
 BOOL bInitialState,        //初始状态,FALSE为无信号,TRUE为有信号
 LPCTSTR lpName         //事件的名称
    );

SetEvent是用来设定事件为有信号,ResetEvent设置事件为无信号。

那事件有信号和无信号到底有什么用,又是怎么用的呢?可以想象以下这样的场景,比如一群人在等候就餐,服务员喊道:38号(有信号)。那38号顾客就可以去就餐,对于那些没被叫道号(无信号)则需继续排队。同样如此,对于多线程只有当该线程有信号时,才能获取CPU事件进而执行相关操作;如果没有信号,则只能继续排队等待(处于阻塞状态)

那线程是怎么获取这时候是否有信号呢?通过WaitForSingleObject函数,下面看函数介绍

    This function returns when the specified object is in the signaled state or when the time-out interval elapses.
     
    DWORD WaitForSingleObject( 
    HANDLE hHandle, 
    DWORD dwMilliseconds ); 
    第一个参数指明对象句柄,我们可以把创建的事件句柄赋予它
    第二个参数表明wait时间。我就等你三年,三年等不到就结婚了....
    最重要的是通过返回值来做进一步操作,该函数主要有几个返回值:
    WAIT_ABANDONED——说明句柄代表的对象是个互斥对象,并且正在被其它线程占用。意思就是说哥们你得等等,我还没完事呢
    WAIT_OBJECT_0——说明句柄对象处于有信号状态
    WAIT_TIMEOUT——在指定的时间内得不到答复(等待超时)且句柄对象处于无信号状态。意思就是你是个好人,今生别等了,下辈子见吧

 

 

二、下面是使用演示

实例一

CreateEvent(NULL, TRUE, TRUE, NULL)——初始状态为有信号,且需手动重置才能为无信号的事件

HANDLE g_hEvent;
DWORD WINAPI procFunc1(LPVOID lpParam)
{
	cout << "start thread1" << endl;

	if (WaitForSingleObject(g_hEvent, 1) == WAIT_OBJECT_0)
	{
		cout << "thread1 is working..." << endl;
	}

	cout << "leve thread1..." << endl;
	return 0;
}

DWORD WINAPI procFunc2(LPVOID lpParam)
{
	cout << "start thread2" << endl;

	if (WaitForSingleObject(g_hEvent, 1) == WAIT_OBJECT_0)//有信号,继续执行
	{
		cout << "thread2 is working..." << endl;
	}

	cout << "leve thread2..." << endl;
	return 0;
}



int main()
{

	g_hEvent = CreateEvent(NULL, TRUE, TRUE, NULL);
	CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)procFunc1, NULL, 0, NULL);
	Sleep(500);
	CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)procFunc2, NULL, 0, NULL);
        return 0
}

可以看到线程1和线程2都完整执行了。因为创建的事件是需手动Reset才会无信号的,所以执行完线程1后事件仍处于有信号状态,所以线程2才能被继续执行

实例二、

再看另一个场景:CreateEvent(NULL, FALSE, TRUE, NULL)——初始状态为有信号且无需手动重置才能为无信号的事件

代码与上几乎相同,区别在与创建事件时参数

 输出

可以看到线程1完整执行了,但是由于信号在执行完线程1后被自动重置为无信号,所以线程2中的逻辑没被执行

实例三、使用SetEvent,ResetEvent



HANDLE g_hEvent = NULL;
DWORD WINAPI procFunc1(LPVOID lpParam)
{
	cout << "start thread1" << endl;

	if (WaitForSingleObject(g_hEvent, 1) == WAIT_OBJECT_0)
	{
		cout << "thread1 is working..." << endl;
	}

	cout << "leve thread1..." << endl;
	ResetEvent(g_hEvent);//重置事件为无信号
	return 0;
}

DWORD WINAPI procFunc2(LPVOID lpParam)
{
	cout << "start thread2" << endl;

	if (WaitForSingleObject(g_hEvent, 1) == WAIT_OBJECT_0)//因为没信号,所以不会执行
	{
		cout << "thread2 is working..." << endl;
	}

	cout << "leve thread2..." << endl;
	return 0;
}



int main()
{
	g_hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
	SetEvent(g_hEvent);
	CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)procFunc1, NULL, 0, NULL);
	Sleep(500);
	CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)procFunc2, NULL, 0, NULL);
}

 

参考:

https://blog.csdn.net/u013407012/article/details/78585431

https://blog.csdn.net/u011394598/article/details/82981399

https://blog.csdn.net/weixin_43935710/article/details/103715571?depth_1-utm_source=distribute.pc_relevant.none-task-blog-BlogCommendFromMachineLearnPai2-2&utm_source=distribute.pc_relevant.none-task-blog-BlogCommendFromMachineLearnPai2-2

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值