必威体育Betway必威体育官网
当前位置:首页 > IT技术

CreateEvent

时间:2019-10-12 05:14:31来源:IT技术作者:seo实验室小编阅读:82次「手机版」
 

createevent

createevent 定义:

  1. handle WINAPI CreateEvent(

  2. _In_opt_ LPSECURITY_ATTRIBUTES lpEventAttributes, //安全属性

  3. _In_ BOOL bManualReset, //设置信号复位方式为自动恢复为无信号状态(FALSE)还是手动恢复为无信号状态(TRUE)

  4. _In_ BOOL bInitialState, //初始状态

  5. _In_opt_ LPCTSTR lpName //信号名称,可以为Null

  6. );

方式一:

hEvent = CreateEvent(NULL, FALSE, TRUE, NULL); //复位方式为自动恢复到无信号状态,且初始状态为有信号.

此时当使用如下表达式后:

Dword dReturn = WaitForSingleObject(hEvent, 等待时间);

hEvent 就会变为无信号状态,如果在某个时候再次需要上面的式子成立并通过,则需要使用下面的语句使其变为有信号状态(此方式只能解锁一个等待线程,如需继续解锁,则需要再次使用下面的式子)

SetEvent(hEvent)

方式二:

hEvent = CreateEvent(NULL, TRUE, TRUE, NULL); //复位方式为手动恢复到无信号状态,且初始状态为有信号.

此时当使用如下表达式后:

dword dReturn = waitforSingleObject(hEvent, 等待时间);  

会自动再次变为有信号状态,上面的式子会直接执行并通过(同时有多个等待线程也会直接执行并通过),如果需要将hEvent设置为无信号状态,则需要手动使用下面的语句:

ResetEvent(hEvent);

注:上面的复位方式指的是恢复到无信号状态的方式,若设置为TRUE,则表示需要手动将其置为无信号,若为FALSE,则会自动变为无信号,千万别和信号量变为有信号状态的方式搞混了!


同步I/O方式打开串口的示例代码

C++代码

  1. HANDLE hCom; //全局变量,串口句柄   
  2. hCom=CreateFile("COM1",//COM1口  
  3.  GENERIC_READ|GENERIC_WRITE, //允许读和写  
  4.  0, //独占方式  
  5.  NULL,  
  6.  OPEN_EXISTING, //打开而不是创建  
  7.  0, //同步方式  
  8.  NULL);   
  9. if(hCom==(HANDLE)-1)   
  10. {  
  11.    AfxmessageBox("打开COM失败!");  
  12.    return FALSE;   
  13. }  
  14. return TRUE;    

  重叠I/O打开串口的示例代码:

C++代码

  1. HANDLE hCom; //全局变量,串口句柄     
  2. hCom =CreateFile("COM1", //COM1口    
  3.  GENERIC_READ|GENERIC_WRITE, //允许读和写    
  4.  0, //独占方式    
  5.  NULL,    
  6.  OPEN_EXISTING, //打开而不是创建     
  7.  FILE_ATTRIBUTE_NORMAL|FILE_FLAG_OVERLAPPED, //重叠方式    
  8.  NULL);     
  9. if(hCom ==INvalid_HANDLE_VALUE)     
  10. {     
  11.    AfxMessageBox("打开COM失败!");     
  12.    return FALSE;     
  13. }     
  14. return TRUE;  

在用ReadFile和WriteFile读写串口时,既可以同步执行,也可以重叠执行。在同步执行时,函数直到操作完成后才返回。这意味着同步执行时线程会被阻塞,从而导致效率下降。在重叠执行时,即使操作还未完成,这两个函数也会立即返回,费时的I/O操作在后台进行。

ReadFile和WriteFile函数是同步还是异步由CreateFile函数决定,如果在调用CreateFile创建句柄时指定了FILE_FLAG_overlapPED标志,那么调用ReadFile和WriteFile对该句柄进行的操作就应该是重叠的;如果未指定重叠标志,则读写操作应该是同步的。ReadFile和WriteFile函数的同步或者异步应该和CreateFile函数相一致。

ReadFile函数只要在串口输入缓冲区中读入指定数量的字符,就算完成操作。而WriteFile函数不但要把指定数量的字符拷入到输出缓冲区,而且要等这些字符从串行口送出去后才算完成操作。

如果操作成功,这两个函数都返回TRUE。需要注意的是,当ReadFile和WriteFile返回FALSE时,不一定就是操作失败,线程应该调用GetLastERROR函数分析返回的结果。例如,在重叠操作时如果操作还未完成函数就返回,那么函数就返回FALSE,而且GetLastError函数返回ERROR_IO_PENDING。这说明重叠操作还未完成。

同步方式读写串口比较简单,下面先例举同步方式读写串口的代码: 

//同步读串口

char str[100];

DWORD wCount;//读取的字节

BOOL bReadStat;

bReadStat=ReadFile(hCom,str,100,&wCount,NULL);

if(!bReadStat) {

AfxMessageBox("读串口失败!");

return false;

}

eturn TRUE;

//同步写串口

char lpOutBuffer[100];

DWORD dwBytesWrite=100;

COMSTAT ComStat;

DWORD dwErrorFlags;

BOOL bWriteStat;

ClearCommError(hCom,&dwErrorFlags,&ComStat);

bWriteStat=WriteFile(hCom,lpOutBuffer,dwBytesWrite,& dwBytesWrite,NULL);

if(!bWriteStat) {

AfxMessageBox("写串口失败!");

}

PurgeComm(hCom, PURGE_TXABORT| PURGE_RXABORT|PURGE_TXCLEAR|PURGE_RXCLEAR);  

在重叠操作时,操作还未完成函数就返回。

重叠I/O非常灵活,它也可以实现阻塞(例如我们可以设置一定要读取到一个数据才能进行到下一步操作)。有两种方法可以等待操作完成:一种方法是用象WaitForSingleObject这样的等待函数来等待OVERLAPPED结构的hEvent成员;另一种方法是调用GetOverlappedResult函数等待,后面将演示说明。

在使用ReadFile和WriteFile重叠操作时,线程需要创建OVERLAPPED结构以供这两个函数使用。线程通过OVERLAPPED结构获得当前的操作状态,该结构最重要的成员是hEvent。hEvent是读写事件。当串口使用异步通讯时,函数返回时操作可能还没有完成,程序可以通过检查该事件得知是否读写完毕。

当调用ReadFile, WriteFile 函数的时候,该成员会自动被置为无信号状态;当重叠操作完成后,该成员变量会自动被置为有信号状态。 

GetOverlappedResult函数 BOOL GetOverlappedResult( HANDLE hFile, // 串口的句柄 // 指向重叠操作开始时指定的LPOVERLAPPED lpOverlapped, //OVERLAPPED结构

LPDWORD lpNumberOfBytesTransferred, // 指向一个32位变量,该变量的值返回实际读写操作传输的字节数。

BOOL bWait  // 该参数用于指定函数是否一直等到重叠操作结束。 // 如果该参数为TRUE,函数直到操作结束才返回。 // 如果该参数为FALSE,函数直接返回,这时如果操作没有完成, // 通过调用GetLastError()函数会返回ERROR_IO_incomplete

);  

该函数返回重叠操作的结果,用来判断异步操作是否完成,它是通过判断OVERLAPPED结构中的hEvent是否被置位来实现的。

异步读串口的示例代码:

char lpInBuffer[1024];

DWORD dwBytesRead=1024;

COMSTAT ComStat;

DWORD dwErrorFlags;

OVERLAPPED m_osRead;

memset(&m_osRead,0,sizeof(OVERLAPPED));

m_osRead.hEvent=CreateEvent(NULL,TRUE,FALSE,NULL);

ClearCommError(hCom,&dwErrorFlags,&ComStat);

dwBytesRead=min(dwBytesRead,(DWORD)ComStat.cbInQue);

if(!dwBytesRead) return FALSE;

BOOL bReadStatus;

bReadStatus=ReadFile(hCom,lpInBuffer, dwBytesRead,&dwBytesRead,&m_osRead);

if(!bReadStatus) //如果ReadFile函数返回FALSE

{

if(GetLastError()==ERROR_IO_PENDING) //GetLastError()函数返回ERROR_IO_PENDING,表明串口正在进行读操作

{

WaitForSingleObject(m_osRead.hEvent,2000); //使用WaitForSingleObject函数等待,直到读操作完成或延时已达到2秒钟 //当串口读操作进行完毕后,m_osRead的hEvent事件会变为有信号

PurgeComm(hCom, PURGE_TXABORT| PURGE_RXABORT|PURGE_TXCLEAR|PURGE_RXCLEAR);

return dwBytesRead;

} return 0;

}

PurgeComm(hCom, PURGE_TXABORT| PURGE_RXABORT|PURGE_TXCLEAR|PURGE_RXCLEAR);

return dwBytesRead;  

相关阅读

CreateEvent使用

Windows API——CREATEEVENT——创建事件 事件是一个允许一个线程在某种情况发生时,唤醒另外一个线程的同步对象。事件告诉线程何

CreateEvent的用法

事件对象就像一个开关:它只有两种状态---开和关。当一个事件处于”开”状态,我们称其为”有信号”否则称为”无信号”。可以在一个

分享到:

栏目导航

推荐阅读

热门阅读