您的位置:首页 > 其它

线程同步之事件对象

2015-12-13 22:16 225 查看
    事件对象有两种不同的类型:人工重置的事件对象和自动重置的时间。当人工重置的事件对象得到通知时,等待该事件对象的所有线程均变为可调用线程。当一个自动重置的对象得到通知时,等待改时间对象的线程中只有一个线程变为可调度线程。

    博主在工作中遇到的的一种需求使用了事件对象。项目需求是要连续向服务端发送文件。每发送一个文件服务器端会生成一个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,那么将创建一个匿名的事件对象。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  信号量 线程同步