if  (!ReadFile  (ghCommport,  lpBuffer,  dwLength,    
                           &dwBytesRead,  &osReader))  //读数据  
{  
    if(  GetLastError()  ==  ERROR_IO_PENDING  ) 
       {      
 if(WaitForSingleObject(osReader.hEvent,1000))
iRecvStrLen=0;//加上这一句                                                                  fWaitingOnRead  =  TRUE;  
     }  
}  

解决方案 »

  1.   

    谢谢 longyii(yiyi) 关注,我再试一下。
      

  2.   

    发一个字符,在CommReadThreadProc里设个断点跟踪一下。
      

  3.   

    CommTimeOuts.WriteTotalTimeoutConstant  =  5000;  
    时间太长了吧
      

  4.   

    上面CommReadThreadProc函数中输漏了一条语句:
    if  ((dwEvtMask  &  EV_RXCHAR)  ==  EV_RXCHAR)前面有这条语句:
    if (WaitCommEvent (...))还是不行,程序不能捕捉所有EV_RXCHAR事件。敬请赐教,解决问题再加分。
      

  5.   

    试试改改中间的值:   //定义超时结构,并填写该结构  
       CommTimeOuts.ReadIntervalTimeout  =  1000;  
       CommTimeOuts.ReadTotalTimeoutMultiplier  =  500;  
       CommTimeOuts.ReadTotalTimeoutConstant  =  5000;  
       CommTimeOuts.WriteTotalTimeoutMultiplier  =  500;  
       CommTimeOuts.WriteTotalTimeoutConstant  = 5000;  
       SetCommTimeouts(  ghCommport,  &CommTimeOuts  )  ;   还有:
        memset(&osReader,0,sizeof(OVERLAPPED));//加上这两句
        memset(&osWriter,0,sizeof(OVERLAPPED));    osReader.hEvent  =  CreateEvent  (NULL,  TRUE,  FALSE,  NULL);  
        osWriter.hEvent  =  CreateEvent  (NULL,  TRUE,  FALSE,  NULL); 
    其它地方看起来太乱,先试试吧,不行再说
      

  6.   

    改改里边的值试试:   COMMTIMEOUTS  CommTimeOuts  ;  
           //定义超时结构,并填写该结构  
       CommTimeOuts.ReadIntervalTimeout  =  1000;  
       CommTimeOuts.ReadTotalTimeoutMultiplier  =  500;  
       CommTimeOuts.ReadTotalTimeoutConstant  =  5000;  
       CommTimeOuts.WriteTotalTimeoutMultiplier  =  500;  
       CommTimeOuts.WriteTotalTimeoutConstant  =  5000;  
       SetCommTimeouts(  ghCommport,  &CommTimeOuts  )  ;   
    还有:
        memset(&osReader,0,sizeof(OVERLAPPED));//加上这两句
        memset(&osWriter,0,sizeof(OVERLAPPED));    osReader.hEvent=CreateEvent(NULL,TRUE,FALSE,NULL);
        osWriter.hEvent=CreateEvent(NULL,TRUE,FALSE,NULL);    
    其它地方看起来太乱,你先试试吧,不行再说
      

  7.   

    longyii(yiyi) 谢谢你的关注!现在出鬼了: 1、我发送字符串“[email protected]”程序捕捉到再次EV_RXCHAR事件,第一次读出8个字符“moon@963”,第二次读出剩下的4个字符“.net”;为什么不能一次读出整个字符串呢? 2、还有就是程序依然不能捕捉所有EV_RXCHAR事件。
      

  8.   

    Caveat
    Using the EV_RXCHAR flag will notify the thread that a byte arrived at the port. This event, used in combination with the ReadFile function, enables a program to read data only after it is in the receive buffer, as opposed to issuing a read that waits for the data to arrive. This is particularly useful when a port is open for nonoverlapped operation because the program does not need to poll for incoming data; the program is notified of the incoming data by the occurrence of the EV_RXCHAR event. Initial attempts to code this solution often produce the following pseudocode, including one oversight covered later in this section:DWORD dwCommEvent;
    DWORD dwRead;
    char  chRead;if (!SetCommMask(hComm, EV_RXCHAR))
       // Error setting communications event mask.for ( ; ; ) {
       if (WaitCommEvent(hComm, &dwCommEvent, NULL)) {
          if (ReadFile(hComm, &chRead, 1, &dwRead, NULL))
             // A byte has been read; process it.
          else
             // An error occurred in the ReadFile call.
             break;
       }
       else
          // Error in WaitCommEvent.
          break;
    }The above code waits for an EV_RXCHAR event to occur. When this happens, the code calls ReadFile to read the one byte received. The loop starts again, and the code waits for another EV_RXCHAR event. This code works fine when one or two bytes arrive in quick succession. The byte reception causes the EV_RXCHAR event to occur. The code reads the byte. If no other byte arrives before the code calls WaitCommEvent again, then all is fine; the next byte to arrive will cause the WaitCommEvent function to indicate the occurrence of the EV_RXCHAR event. If another single byte arrives before the code has a chance to reach the WaitCommEvent function, then all is fine, too. The first byte is read as before; the arrival of the second byte causes the EV_RXCHAR flag to be set internally. When the code returns to the WaitCommEvent function, it indicates the occurrence of the EV_RXCHAR event and the second byte is read from the port in the ReadFile call.The problem with the above code occurs when three or more bytes arrive in quick succession. The first byte causes the EV_RXCHAR event to occur. The second byte causes the EV_RXCHAR flag to be set internally. The next time the code calls WaitCommEvent, it indicates the EV_RXCHAR event. Now, a third byte arrives at the communications port. This third byte causes the system to attempt to set the EV_RXCHAR flag internally. Because this has already occurred when the second byte arrived, the arrival of the third byte goes unnoticed. The code eventually will read the first byte without a problem. After this, the code will call WaitCommEvent, and it indicates the occurrence of the EV_RXCHAR event (from the arrival of the second byte). The second byte is read, and the code returns to the WaitCommEvent function. The third byte waits in the system’s internal receive buffer. The code and the system are now out of sync. When a fourth byte finally arrives, the EV_RXCHAR event occurs, and the code reads a single byte. It reads the third byte. This will continue indefinitely.The solution to this problem seems as easy as increasing the number of bytes requested in the read operation. Instead of requesting a single byte, the code could request two, ten, or some other number of bytes. The problem with this idea is that it still fails when two or more extra bytes above the size of the read request arrive at the port in quick succession. So, if two bytes are read, then four bytes arriving in quick succession would cause the problem. Ten bytes requested would still fail if twelve bytes arrived in quick succession.The real solution to this problem is to read from the port until no bytes are remaining. The following pseudocode solves the problem by reading in a loop until zero characters are read. Another possible method would be to call ClearCommError to determine the number of bytes in the buffer and read them all in one read operation. This method requires more sophisticated buffer management, but it reduces the number of reads when a lot of data arrives at once.DWORD dwCommEvent;
    DWORD dwRead;
    char  chRead;if (!SetCommMask(hComm, EV_RXCHAR))
       // Error setting communications event maskfor ( ; ; ) {
       if (WaitCommEvent(hComm, &dwCommEvent, NULL)) {
          do {
             if (ReadFile(hComm, &chRead, 1, &dwRead, NULL))
                // A byte has been read; process it.
             else
                // An error occurred in the ReadFile call.
                break;
          } while (dwRead);
       }
       else
          // Error in WaitCommEvent
          break;
    }The above code does not work correctly without setting the proper time-outs. Communications time-outs, discussed later, affect the behavior of the ReadFile operation in order to cause it to return without waiting for bytes to arrive. Discussion of this topic occurs later in the “Communications Time-outs” section of this article.The above caveat regarding EV_RXCHAR also applies to EV_RXFLAG. If flag characters arrive in quick succession, EV_RXFLAG events may not occur for all of them. Once again, the best solution is to read all bytes until none remain.The above caveat also applies to other events not related to character reception. If other events occur in quick succession some of the notifications will be lost. For instance, if the CTS line voltage starts high, then goes low, high, and low again, an EV_CTS event occurs. There is no guarantee of how many EV_CTS events will actually be detected with WaitCommEvent if the changes in the CTS line happen quickly. For this reason, WaitCommEvent cannot be used to keep track of the state of the line. Line status is covered in the “Modem Status” section later in this article.Serial Communications in Win32
      

  9.   

    你在接收时应该这样写:
    ClearCommError(hCommDev,&dwErrorFlag,&comStat);
    iRecvStrLen=comStat.cbInQue;
    if(iRecvStrLen>0)
    {
        BOOL bReturn=ReadFile(ghCommport,lpBuffer,dwLength,    
                               &dwBytesRead,  &osReader); 
        if(!bReturn)
        {
    if(ERROR_IO_PENDING==GetLastError())
    {
        if(WaitForSingleObject(read_os.hEvent,2000))
    iRecvStrLen=0;
    }
    else
    {
        MessageBox("Error on ReadFile!");
        return -1;
    }
        }
        ...
    }如果还不行
    在ReadFile()之前适当延时,如:Sleep(1000);
      

  10.   

    谢谢xiaoyuer(我是一只虫) 的提示,更谢谢longyii(yiyi) 的帮助。
    还是不行,没招了,只好改成一次读一个字符:
    for ( ; ; ) 
    {
      if (WaitCommEvent(ghCommport, &dwEvtMask, NULL)) 
      {
        do 
        {
          if (ReadFile(ghCommport, lpBuffer, 1, &dwBytesRead, NULL)
          {
            // A byte has been read; process it.
          }
          else
          {
            // An error occurred in the ReadFile call.
          }
        } while (dwBytesRead);
      }
      else
      {
        // Error in WaitCommEvent
      }
    }不过又有新问题了:
    每次打开串口,关闭串口之后,必须等一会才能再次打开串口,为什么呢?
    莫非是COMMTIMEOUTS  CommTimeOuts 的值设定有问题?
      

  11.   

    多谢大家的帮助,终于搞定,答案在Serial Communications in Win32中!