C++ 线程同步之 事件的使用

多线程同步有很多方法,现在简单记录一下自己的程序对事件的使用。

 

包含的头文件

#include<Windows.h>


事件的使用步骤:(最简单的使用步骤)

1、定义一个句柄,用于事件的标识。

HANDLE     aEvent;


2、创建事件(可以和第一个合并,注意对象的生存周期和作用范围):

aEvent  =  CreateEvent(NULL,FALSE,FALSE,NULL);

这样就创建了一个event,以后这个event就用aEvent标识。


3、等待事件被触发(这是最核心的地方,与第4步结合使用,用于多线程同步)。

WaitForSingleObject(aEvent ,3000);

意思就是当代码执行到这的时候,就会在此处阻塞着,直到另外一个线程里触发这个事件后(第4步)或者等待超时后,才会继续往下执行。

(此处的事件若是为NULL,那么程序会马上返回一个很大的DWORD (4294967295),程序继续往下执行,很容易造成程序里不可思议的错误。此处一定要小心)

#include<stdio.h>
#include<Windows.h>

void main()
{
 HANDLE hMyEvent;
 hMyEvent = CreateEvent(NULL,FALSE,FALSE,NULL);
 //while (WaitForSingleObject(hMyEvent, 3000) != WAIT_OBJECT_0)
 DWORD result = WaitForSingleObject(NULL, 3000);
 while (result != WAIT_OBJECT_0)
 {
  printf("等待超时!!\n");
  
 }

}

 


4、触发事件(与第三步结合使用,进行线程同步)。

SETEVENT(aEvent);

当线程里执行完这句代码之后,另外一个线程中阻塞等待该事件处(第三步)才会继续往下执行。

5、关闭句柄(当这个事件用完之后,要关闭句柄释放资源)。

CloseHandle(aEvent);



例子:(从业务中摘出的代码,只作例子,不能运行)


static unsigned int __stdcall GetPortThread(void* param);

uintptr_t   g_GetPortTh = NULL;//获取串口号线程句柄
HANDLE g_GetPortEvent = NULL;//获取串口号事件
LONG   g_TheGetPort = -1; // 获取到的设备所在串口号

g_GetPortEvent = CreateEvent(NULL , TRUE , FALSE , NULL);


main()

{

unsigned int nowBaudRate = 0;

//建立线程
g_GetPortTh = _beginthreadex(NULL,0,GetPortThread,NULL,0,NULL);

DWORD waitIndex = WaitForSingleObject(g_GetPortEvent,2000);
if ( WAIT_TIMEOUT == waitIndex )
{
return -1;
}
else
{
return g_TheGetPort;
}

}

unsigned int  __stdcall CPatrolCtrlCtrl::GetPortThread(void* param)
{
unsigned int nowBaudRate = 0;
int i = 1;
for (;i<=16;i++)
{
if(SDT_GetCOMBaud(i,&nowBaudRate)==0x90)
{
g_TheGetPort = i;
SetEvent(g_GetPortEvent);//激活系统介素事件
return 0;
}
}
g_TheGetPort = -1;
return -1;
}

 


 

看完最简单的使用步骤后,就明白了事件到底是干什么的。但有时编程过程中会遇到很多复杂的情况,这就需要更复杂的使用方法。


主要有几点:


1、等待事件被触发函数有:

DWORD WaitForMultipleObjects(DWORD nCount, const HANDLE* lpHandles,BOOL bWaitAll,DWORD dwMilliseconds);

这个函数的参数:第一个是等待事件的个数,第二个是等待的事件的数组,第三个是等待事件全部被触发了才往下执行,还是只要有一个被触发了就往下执行,第四个是超时时间。


2、将事件设置为无信号状态(被触发之后重置)

ResetEvent();

在自动重置事件对象中,当WaitSingleObject/WaitForMultipleObjects接收到SetEvent发送过来的信号后则返回WAIT_OBJECT_0,此时操作系统(待定)自动重置等待的事件对象(即自动将其设置为无信号状态。无论何时通过SetEvent发送过来的信号,只要未被接收到均不会被自动重置。但在未被接收之前可以调用ResetEvent手动重置等待的事件对象,此时等待的事件对象为无信号状态)。在手动重置事件对象中,当WaitSingleObject/WaitForMultipleObjects接收到SetEvent发送过来的信号后则返回WAIT_OBJECT_0,此时需要调用ResetEvent手动重置等待的事件对象(即手动将其设置为无信号状态)。

3、BOOL bManualReset,BOOL bInitialState,   LPTSTRlpName); 

4、BOOL PulseEvent(HANDLE hEvent);

5、 HANDLE OpenEvent(DWORD dwDesiredAccess, BOOL bInheritHandle, LPCTSTRlpName); 









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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值