线程同步之事件对象
2015-12-13 22:16
225 查看
事件对象有两种不同的类型:人工重置的事件对象和自动重置的时间。当人工重置的事件对象得到通知时,等待该事件对象的所有线程均变为可调用线程。当一个自动重置的对象得到通知时,等待改时间对象的线程中只有一个线程变为可调度线程。
博主在工作中遇到的的一种需求使用了事件对象。项目需求是要连续向服务端发送文件。每发送一个文件服务器端会生成一个id返回给服务器端。但客户端的发送和服务端的回复会采用异步方式,这样就会产生一个问题,如果使用循环连续发送文件,服务器端不一定会按照发送的顺序返回id(也许服务器端会做相应的处理,但我们不应把容错都寄托到别人身上,自己应该尽量避免发生其他人会发生错误)。这时我们可以使用时间对象来避免该情况的发生。
循环发送的代码如下:
下面对用到的几个api做一下说明:
CreateEvent函数创建或打开一个命名的或者匿名的时间对象,该函数原型为:
HANDLE CreateEvent(LPSECURITY_ATTRIBUTES lpEventAttributes,
BOOL bManualReset,
BOOL bInitialState,
LPCTSTR lpName);
lpEventAttributes指向SECURITY_ATTRIBUTES结构体的指针。如果其值为NULL,则使用默认的安全性。
bManualReset,指定创建的忍冬重置事件对象,还是自动重置事件对象。如果此参数为TRUE,表示该函数将创建一个人工重置事件对象;如果此参数为FALSE,表示该函数将创建一个自动重置事件对象。如果是人工重置事件对象,当线程等待到该对象的所有权之后,需要调用ResetEvent函数手动的将该事件对象设置为无信号状态;如果是自动重置事件对象,当线程等到该函数的所有权之后,系统会自动将该对象设置为无信号状态。
bInitialState指定事件对象的初始状态。如果此参数值为真,那么该事件对象初始是有信号状态;否则是无信号状态。在该程序中我们设置为false,表示第一次运行到WaitForSingleObject函数处就停止,等到服务器返回后将事件置为有信号状态,才可以向下继续进行。
lpName指定对象的名称。如果此参数值为NULL,那么将创建一个匿名的事件对象。
博主在工作中遇到的的一种需求使用了事件对象。项目需求是要连续向服务端发送文件。每发送一个文件服务器端会生成一个id返回给服务器端。但客户端的发送和服务端的回复会采用异步方式,这样就会产生一个问题,如果使用循环连续发送文件,服务器端不一定会按照发送的顺序返回id(也许服务器端会做相应的处理,但我们不应把容错都寄托到别人身上,自己应该尽量避免发生其他人会发生错误)。这时我们可以使用时间对象来避免该情况的发生。
循环发送的代码如下:
HANDLE hSemaphore;
hSemaphore = CreateEvent(NULL,TRUE,FALSE,NULL); for(int m_iIndex=0;m_iIndex<m_vSendFileInfo.size();m_iIndex++) { string surl,stype; stype = "DOCUMENT"; surl = "https://test.sendfile.io"; CRestHttpClient msgurl(surl); msgurl.addParmas("filename",m_vSendFileInfo[m_iIndex].filename); msgurl.addParmas("length",m_vSendFileInfo[m_iIndex].length); msgurl.addParmas("type",stype); msgurl.DoPut(CBUploadFile,sFileInfo,m_vSendFileInfo[m_iIndex].sFilePath); string sTipText = "正在上传文件:" + m_vSendFileInfo[m_iIndex].filename; WaitForSingleObject(hSemaphore, 10000); ResetEvent(hSemaphore); }接收端则需要在收到回复后SetEvent(hSemaphore)即可。这样就可以在异步通信中模拟同步时间了。
下面对用到的几个api做一下说明:
CreateEvent函数创建或打开一个命名的或者匿名的时间对象,该函数原型为:
HANDLE CreateEvent(LPSECURITY_ATTRIBUTES lpEventAttributes,
BOOL bManualReset,
BOOL bInitialState,
LPCTSTR lpName);
lpEventAttributes指向SECURITY_ATTRIBUTES结构体的指针。如果其值为NULL,则使用默认的安全性。
bManualReset,指定创建的忍冬重置事件对象,还是自动重置事件对象。如果此参数为TRUE,表示该函数将创建一个人工重置事件对象;如果此参数为FALSE,表示该函数将创建一个自动重置事件对象。如果是人工重置事件对象,当线程等待到该对象的所有权之后,需要调用ResetEvent函数手动的将该事件对象设置为无信号状态;如果是自动重置事件对象,当线程等到该函数的所有权之后,系统会自动将该对象设置为无信号状态。
bInitialState指定事件对象的初始状态。如果此参数值为真,那么该事件对象初始是有信号状态;否则是无信号状态。在该程序中我们设置为false,表示第一次运行到WaitForSingleObject函数处就停止,等到服务器返回后将事件置为有信号状态,才可以向下继续进行。
lpName指定对象的名称。如果此参数值为NULL,那么将创建一个匿名的事件对象。
相关文章推荐
- linux多线程编程详解教程(线程通过信号量实现通信代码)
- c#线程同步使用详解示例
- Linux线程同步之信号C语言实例
- JAVA 多线程之信号量(Semaphore)实例详解
- Java线程同步实例分析
- JAVA生产者消费者(线程同步)代码学习示例
- 多线程问题及处理方法【转】
- Linux设备驱动并发控制详解(自旋锁,信号量)
- 线程同步问题
- 信号量
- 信号量、互斥锁,读写锁和条件变量的区别
- CountDownLatch和CyclicBarrier的区别
- 互斥锁与条件变量的配合!
- 信号量 互斥锁 条件变量的区别
- 关于哲学家就餐问题 源代码(linux)
- 用户模式下线程同步(一)
- 黑马程序员_张孝祥7k面试题_银行调度系统
- 多个生产者与多个消费者的问题
- Posix信号量
- 使用信号量和关键区来实现生产者消费者