void myReceiveChar(void)
{
COMSTAT commstat;//这个结构体主要是用来获取端口信息的
HANDLE hlocEvent;
DWORD dwError;
DWORD dwMask;
DWORD dwLength;
DWORD dwByteReaded;
DWORD i;
uint8_t byRecBuf[4096];
OVERLAPPED overlapped; //OVERLAPPED结构体用来设置I/O异步,具体可以参见MSDN
memset(&overlapped, 0, sizeof(OVERLAPPED)); //初始化OVERLAPPED对象
memset(&commstat, 0, sizeof(commstat));
hlocEvent = CreateEvent(NULL, TRUE, FALSE, NULL); //创建CEvent对象
overlapped.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL); //创建CEvent对象
SetEvent(hlocEvent); //标记事件
while(1) //若端口处于打开状态,则一直读取消息
{
ClearCommError(hComm, &dwError, &commstat);
if(commstat.cbInQue) //如果串口inbuf中有接收到的字符就执行下面的操作
{
mRecBuf.dwRxEnd=FALSE;
WaitForSingleObject(hlocEvent, INFINITE); //无限等待
ResetEvent(hlocEvent); //清标记事件
memset(&mosRead,0,sizeof(OVERLAPPED));
//清除硬件的通讯错误以及获取通讯设备的当前状态
ClearCommError(hComm, &dwError, &commstat);
dwLength = commstat.cbInQue;
if(TRUE == ReadFile(hComm, byRecBuf, dwLength, &dwByteReaded, &mosRead))
{
for(i=0;i<dwByteReaded;i++) //按字节将接收到的数据写入接收环形缓冲区
{
dwError = CycBufWrite(&mRecBuf,byRecBuf[i]);
if(dwError==CB_FULL) //直到缓冲区被写满
break;
}
}
/**/
if(!WaitCommEvent(hComm, &dwMask, &overlapped))
{
if(GetLastError()==ERROR_IO_PENDING)//如果操作被挂起,也就说正在读取或正在写,则进行下面的操作
GetOverlappedResult(hComm,&overlapped, &dwLength, TRUE); //无限等待这个I/O操作的完成
else
{
CloseHandle(overlapped.hEvent);
return;
}
}
测试时发现,当如果在抛出消息后马上ClearCommError,将有可能引起程序进入死循环
SetEvent(hlocEvent); //设置CEvent对象为无信号状态
continue;
}
else
{
mRecBuf.dwRxEnd=TRUE;//接收空闲状态
}
/**/
Sleep(10);
}
CloseHandle(overlapped.hEvent);
return;
}
事件定义
HANDLE hlocEvent;
创建事件对象
hlocEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
SetEvent(hlocEvent); //标记事件
ResetEvent(hlocEvent); //清标记事件
等待事件发生,包含了时间的等待
WaitForSingleObject(hlocEvent, INFINITE); //无限等待
事件对象与全局变量的差异
1.全局变量操作不是原子操作,event是可以保证原子操作的
2.事件在等待的时候,线程挂起,不占用CPU资源,全局变量需要一直查询,一直处于忙等待