while(!GetOverlappedResult(m_hCom ,&(m_rdos), &dwLength, TRUE ))
{
dwError = GetLastError();
if(dwError == ERROR_IO_INCOMPLETE)
continue;
else
{
wsprintf( szError, "<CE-%u>", dwError ) ;
ClearCommError(m_hCom , &dwErrorFlags, &ComStat ) ;
break;
}
}
请注意 ERROR_IO_INCOMPLETE 、ERROR_IO_PENDING 的意义:(MSDN里的)
996 Overlapped I/O event is not in a signaled state. ERROR_IO_INCOMPLETE
997 Overlapped I/O operation is in progress. ERROR_IO_PENDING 通过上面对ERROR_IO_INCOMPLETE的意思可知,在这个while()循环中,调用GetOverlappedResult()函数来获取实际的读取的字符数时,直到异步IO事件有效时才break;否则(无效时:即为ERROR_IO_INCOMPLETE时)继续等待。上午没有看清你的层次结构,误解了,不好意思。
一句话,就是等待异步IO信号有效,以通过GetOverlappedResult()函数获取实际的读取的字符数。
{
dwError = GetLastError();
if(dwError == ERROR_IO_INCOMPLETE)
continue;
else
{
wsprintf( szError, "<CE-%u>", dwError ) ;
ClearCommError(m_hCom , &dwErrorFlags, &ComStat ) ;
break;
}
}
请注意 ERROR_IO_INCOMPLETE 、ERROR_IO_PENDING 的意义:(MSDN里的)
996 Overlapped I/O event is not in a signaled state. ERROR_IO_INCOMPLETE
997 Overlapped I/O operation is in progress. ERROR_IO_PENDING 通过上面对ERROR_IO_INCOMPLETE的意思可知,在这个while()循环中,调用GetOverlappedResult()函数来获取实际的读取的字符数时,直到异步IO事件有效时才break;否则(无效时:即为ERROR_IO_INCOMPLETE时)继续等待。上午没有看清你的层次结构,误解了,不好意思。
一句话,就是等待异步IO信号有效,以通过GetOverlappedResult()函数获取实际的读取的字符数。
http://www.csdn.net/expert/topic/713/713616.xml?temp=.6165277
dwLength, &dwLength, &( m_rdos) ) ;//读串口,假设共有8个子节,我每次读4个,读了一次,没读完,往下走
if (!fReadStat)//pass
{
if (GetLastError() == ERROR_IO_PENDING) //没有读完,pass
{
while(!GetOverlappedResult(m_hCom ,
&( m_rdos), &dwLength, TRUE )) {
dwError = GetLastError();//这时
//readfile的msdn中又这么一段
//The event specified in the OVERLAPPED structure is set to the
//signaled
//state upon completion of the read operation.这就是“异步IO事
//件”吗?
//我认为这时是无信号状态
if(dwError == ERROR_IO_INCOMPLETE) // 所以pass
continue;// 到了这儿好象还是不能回到ReadFile呀,对了,我这个程序是在一个Timer定时处理函数中的一段代码,但好像形成死循环了呀?请恕我愚笨!
else
{
wsprintf( szError, "<CE-%u>", dwError ) ;
ClearCommError(m_hCom , &dwErrorFlags, &ComStat ) ;
break;
}
}
………..
在设置了异步IO操作后,IO操作和函数返回有以下两种情况:
1.函数返回时IO操作已完成:此时结果好像是同步执行的,但实际上这是异步执行的结果 。
2.函数返回时IO操作还没完成:此时一方面,函数返回值为0,并且GetLastError()函数返回ERROR_IO_PENDING:另一方面,系统把OVERLAPPED中的信号事件设为无信号状态。当IO操作完成时,系统把它设置为有信号状态。
3.异步IO操作可以由GetOverlappedResult()来获取结果,也可以用WINDOWS信号函数来处理。
4.GetOverlappedResult()最后一参数指定函数是否等待挂起的异步操作完成。为1,等待完成后返回,如果为0,同时操作处于挂 起状态,则该函数返回0,并且GetLastError函数返回ERROR_IO_INCOMPLETE.好了,有什么好的想法,来信告诉我:[email protected]共同学习!
"ReadFile()函数调用成功,则返回值不为0,否则,为0.请看上面第1、2点.
fReadStat = ReadFile(m_hCom, lpszBlock,dwLength, &dwLength, &( m_rdos) ) ;//读串口
if (!fReadStat)
{
//执行到这里,表示读数据还没有完成(不管你读多少数据,当然是由你的dwLength指定),因为你用异步(指定的OVERLAPPED结构)操作读取数据,而异步操作是不等待函数执行完成的。此时系统把OVERLAPPED中的信号事件设为无信号状态,在调用GetOverlappedResult(m_hCom ,&( m_rdos), &dwLength, TRUE )来获取结果时,必须等待到有信号状态。当IO操作完成时,系统把它设置为有信号状态。所以调用GetOverlappedResult(m_hCom ,&( m_rdos), &dwLength, TRUE )才能获得真正读到的结果。感觉怎样?我也是在学习!!呵呵~~~~~~
to qiuanhong(练从难处练,用从易处用) :
帮我看看!
http://www.csdn.net/expert/topic/712/712759.xml?temp=.4088709
1。readfile执行之后,它开了一个线程,如果读完了,线程也就结束了,如果没有读完,IO线程挂起。
2。GetOverlappedResult只是一个等待的线程,起延时作用。
3。readfile在这段延时的时间内,又重新读串口,是这样的吗?这个没有任何东西触发它呀,难道它有一个自身定时的循环,只要有时间,就能多次读数据?
初学,没人指导真是痛苦。
非常感谢您,我的信箱[email protected],到时候发信给您!!
有点乱,但肯定好用UINT ReadCommThread(LPVOID pParam)
{
char szReadBuf[300]; //读缓冲
int n,k,j,x; //记数
DWORD dwEvent,dwError; //
COMSTAT cs;
OVERLAPPED OLwait; //重叠结构
CString cstrCount,cstrTemp; //暂存
MSG msg; //消息体
OLwait.hEvent=CreateEvent(NULL, FALSE, FALSE, NULL);
CMyCommDlg * pMyDlg =(CMyCommDlg *)pParam;
if(OLwait.hEvent==NULL||!SetCommMask(pMyDlg->m_myComm.m_hCom,EV_RXCHAR|EV_RING))
{
pMyDlg->PostMessage(WM_MSG,1,1);
return 0;
}
k=0;
j=0;
for(;;)
{
while(PeekMessage(&msg,NULL,0,0,PM_REMOVE)) //消息泵
{
if(msg.message==WM_STOP) //收到退出消息
return 0;
}
if(!WaitCommEvent(pMyDlg->m_myComm.m_hCom,&dwEvent,&OLwait))
{
// k++;
// cstrCount.Format("WaitCommEvent %d\n",k);
// OutputDebugString(cstrCount);
if(x=GetLastError()==ERROR_IO_PENDING)
{ if(WaitForSingleObject(OLwait.hEvent,INFINITE)==WAIT_OBJECT_0) //等500ms
{
ClearCommError(pMyDlg->m_myComm.m_hCom,&dwError,&cs);
if(dwEvent&EV_RING)
OutputDebugString("Found a Ring\n");
if(cs.cbInQue>0 && dwEvent&EV_RXCHAR)
{
j++;
cstrTemp=pMyDlg->m_cstrReceive;
n=pMyDlg->m_myComm.ReadCommBlock(&pMyDlg->m_myComm,(char *)szReadBuf,cs.cbInQue);
pMyDlg->m_cstrReceive.Format ("%s",szReadBuf);
pMyDlg->m_cstrReceive=pMyDlg->m_cstrReceive.Left(n); //取实际读到的字节数的串
pMyDlg->m_cstrReceive=cstrTemp+pMyDlg->m_cstrReceive;
pMyDlg->PostMessage(WM_MSG,0,0);
// cstrCount.Format("ReadCommBlock %d\n",j);
// OutputDebugString(cstrCount);
}
} // WaitForSingleObject()
} // GetLastError()
else
{
cstrCount.Format("WriteEorro %d\n",x);
OutputDebugString(cstrCount); Sleep(1);
pMyDlg->PostMessage(WM_MSG,1,1);
return 1; //可能是串口错误
}
} // WaitCommEvents()
else
{
Sleep(1);
}
}
return 0;
}
2。GetOverlappedResult只是一个等待的线程,起延时作用。
GetOverlappedResult()是等待直到信号状态变为有产,而ReadFile()操作没有完成时,信号是无效的(上面第2点),当ReadFile()操作完成后,系统把它(前面无效信号)设置为有信号状态。当信号为有效后,GetOverlappedResult()函数才执行成功(返回非0,退出while()循环).所以它并不是起延时作用,而是等待读操作完成来获取实际读得的字符数。3。readfile在这段延时的时间内,又重新读串口,是这样的吗?这个没有任何东西触发它呀,难道它有一个自身定时的循环,只要有时间,就能多次读数据?
这一点,相信看了刚才第2个问题你会理解的了---------ReadFile()是一直在读取数据的,直到读成功。而GetoverlappedResult()只是对这一次Readfile()(注意是只这一次)获取该次的结果,或许只1个字符(你在ReadFile里指定每次读取的字符数)在这里,你可能没读懂,ReadFile()外面应该还有个大的While()循环)。
也就是说,当GetoverlappedResult()成功后,将继续读取输入缓冲区中的下一比数据,因而会继续重复你上面的代码的动作。