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()函数获取实际的读取的字符数。

解决方案 »

  1.   

    请看:
    http://www.csdn.net/expert/topic/713/713616.xml?temp=.6165277
      

  2.   

    万分感谢您,分收到了吗?我把我对程序的理解写了一下,请您看对不对?关于“异步IO事件”的理解不知对不?     fReadStat = ReadFile(m_hCom, lpszBlock,
                        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;
                   }
    }
    ………..
      

  3.   

    仔细体会一下下面的意思:
    在设置了异步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]共同学习!
      

  4.   

    "大侠,我始终不明白的一点是,明明readfile已经执行完了,到了GetOverlappedResult,即使它再等也无法再读到未读完的串口数据呀,我的猜想是readfile一直在某一个线程里等待,而GetOverlappedResult触发了它,让它执行,它读完之后,也触发GetOverlappedResult的完成。
    "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 )才能获得真正读到的结果。感觉怎样?我也是在学习!!呵呵~~~~~~
             
      

  5.   

    说得不错,不过GetOverlappedResult()在98、2k下的运行结果可能有些出入。
    to qiuanhong(练从难处练,用从易处用) :
    帮我看看!
    http://www.csdn.net/expert/topic/712/712759.xml?temp=.4088709
      

  6.   

    感觉你真的很好,衷心谢谢你!我看了您的解释后收获很大,我是这样理解的,
    1。readfile执行之后,它开了一个线程,如果读完了,线程也就结束了,如果没有读完,IO线程挂起。
    2。GetOverlappedResult只是一个等待的线程,起延时作用。
    3。readfile在这段延时的时间内,又重新读串口,是这样的吗?这个没有任何东西触发它呀,难道它有一个自身定时的循环,只要有时间,就能多次读数据?
    初学,没人指导真是痛苦。
    非常感谢您,我的信箱[email protected],到时候发信给您!!
      

  7.   

    这是另一种方法,看不懂的最好去查msdn,这样才能真正掌握!
    有点乱,但肯定好用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;
    }
      

  8.   

    下面两点我觉得不是很好:(对了,只是我个人的理解)
    2。GetOverlappedResult只是一个等待的线程,起延时作用。
      GetOverlappedResult()是等待直到信号状态变为有产,而ReadFile()操作没有完成时,信号是无效的(上面第2点),当ReadFile()操作完成后,系统把它(前面无效信号)设置为有信号状态。当信号为有效后,GetOverlappedResult()函数才执行成功(返回非0,退出while()循环).所以它并不是起延时作用,而是等待读操作完成来获取实际读得的字符数。3。readfile在这段延时的时间内,又重新读串口,是这样的吗?这个没有任何东西触发它呀,难道它有一个自身定时的循环,只要有时间,就能多次读数据?
      这一点,相信看了刚才第2个问题你会理解的了---------ReadFile()是一直在读取数据的,直到读成功。而GetoverlappedResult()只是对这一次Readfile()(注意是只这一次)获取该次的结果,或许只1个字符(你在ReadFile里指定每次读取的字符数)在这里,你可能没读懂,ReadFile()外面应该还有个大的While()循环)。
    也就是说,当GetoverlappedResult()成功后,将继续读取输入缓冲区中的下一比数据,因而会继续重复你上面的代码的动作。