估计你的程序中waitForMultipliObjects返回的值是WAIT_FAILED(0XFFFFFFFF).调用getlasterror可以获得进一步的信息.最大的可能是g_Event中有无效的句柄.

解决方案 »

  1.   

    调用getlasterror后,用FormatMessage()  没有返回的东西
    g_Event 在查看地址时均有效
      

  2.   

    There are two interesting side effects of SetCommMask and WaitCommEvent. First, if the communications port is open for nonoverlapped operation, WaitCommEvent will be blocked until an event occurs. If another thread calls SetCommMask to set a new event mask, that thread will be blocked on the call to SetCommMask. The reason is that the original call to WaitCommEvent in the first thread is still executing. The call to SetCommMask blocks the thread until the WaitCommEvent function returns in the first thread. This side effect is universal for ports open for nonoverlapped I/O. If a thread is blocked on any communications function and another thread calls a communications function, the second thread is blocked until the communications function returns in the first thread. The second interesting note about these functions is their use on a port open for overlapped operation. If SetCommMask sets a new event mask, any pending WaitCommEvent will complete successfully, and the event mask produced by the operation is NULL.
      

  3.   

    看看下面这段程序,对你可能有帮助:
    BOOL CSerial::Open( int nPort, int nBaud )
    {
    if( m_bOpened ) return( TRUE );char szPort[15];
    DCB dcb;wsprintf( szPort, "COM%d", nPort );
    m_hComDev = CreateFile( szPort, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED, NULL );
    if( m_hComDev == NULL ) return( FALSE );memset( &m_OverlappedRead, 0, sizeof( OVERLAPPED ) );
    memset( &m_OverlappedWrite, 0, sizeof( OVERLAPPED ) );COMMTIMEOUTS CommTimeOuts;
    CommTimeOuts.ReadIntervalTimeout = 0xFFFFFFFF;
    CommTimeOuts.ReadTotalTimeoutMultiplier = 0;
    CommTimeOuts.ReadTotalTimeoutConstant = 0;
    CommTimeOuts.WriteTotalTimeoutMultiplier = 0;
    CommTimeOuts.WriteTotalTimeoutConstant = 5000;
    SetCommTimeouts( m_hComDev, &CommTimeOuts );m_OverlappedRead.hEvent = CreateEvent( NULL, TRUE, FALSE, NULL );
    m_OverlappedWrite.hEvent = CreateEvent( NULL, TRUE, FALSE, NULL );dcb.DCBlength = sizeof( DCB );
    GetCommState( m_hComDev, &dcb );
    dcb.BaudRate = nBaud;
    dcb.ByteSize = 8;
    if( !SetCommState( m_hComDev, &dcb ) ||
    !SetupComm( m_hComDev, 10000, 10000 ) ||
    m_OverlappedRead.hEvent == NULL ||
    m_OverlappedWrite.hEvent == NULL ){
    DWORD dwError = GetLastError();
    if( m_OverlappedRead.hEvent != NULL ) CloseHandle( m_OverlappedRead.hEvent );
    if( m_OverlappedWrite.hEvent != NULL ) CloseHandle( m_OverlappedWrite.hEvent );
    CloseHandle( m_hComDev );
    return FALSE;
    }m_bOpened = TRUE;return m_bOpened;}int CSerial::InBufferCount( void )
    {if( !m_bOpened || m_hComDev == NULL ) return( 0 );DWORD dwErrorFlags;
    COMSTAT ComStat;ClearCommError( m_hIDComDev, &dwErrorFlags, &ComStat );return (int)ComStat.cbInQue;}DWORD CSerial::ReadData( void *buffer, DWORD dwBytesRead)
    {if( !m_bOpened || m_hComDev == NULL ) return 0;BOOL bReadStatus;
    DWORD dwErrorFlags;
    COMSTAT ComStat;ClearCommError( m_hComDev, &dwErrorFlags, &ComStat );
    if( !ComStat.cbInQue ) return 0;dwBytesRead = min(dwBytesRead,(DWORD) ComStat.cbInQue);bReadStatus = ReadFile( m_hComDev, buffer, dwBytesRead, &dwBytesRead, &m_OverlappedRead );
    if( !bReadStatus ){
    if( GetLastError() == ERROR_IO_PENDING ){
    WaitForSingleObject( m_OverlappedRead.hEvent, 2000 );
    return dwBytesRead;
    }
    return 0;
    }return dwBytesRead;}DWORD CSerial::SendData( const char *buffer, DWORD dwBytesWritten)
    {if( !m_bOpened || m_hComDev == NULL ) return( 0 );BOOL bWriteStat;bWriteStat = WriteFile( m_hComDev, buffer, dwBytesWritten, &dwBytesWritten, &m_OverlappedWrite );
    if( !bWriteStat){
    if ( GetLastError() == ERROR_IO_PENDING ) {
    WaitForSingleObject( m_OverlappedWrite.hEvent, 1000 );
    return dwBytesWritten;
    }
    return 0;
    }
    return dwBytesWritten;}
      

  4.   

    To: joyu(佳友) ,我也下过此段程序
    但是,我觉得我所有的事都做了,还是不会停,各位没有遇到过吗?
    以下是我的部分程序
    m_ComHandle = CreateFile(Lpcom,GENERIC_READ|GENERIC_WRITE,
                 0,0,OPEN_EXISTING,                           FILE_ATTRIBUTE_NORMAL|FILE_FLAG_OVERLAPPED ,NULL);
    if(m_ComHandle==NULL)
    {
                  ……
    }

    SetupComm(m_ComHandle,Rbuf,Wbuf);//Rbuf和Wbuf默认1024 SetTimeOut(ReadIntervalTimeout,ReadTotalTimeoutConstant,ReadTotalTimeoutMultiplier,WriteTotalTimeoutConstant,WriteTotalTimeoutMultiplier);// 自定义函数
    SetDCB(););// (1)自定义函数在下面 PurgeComm(m_ComHandle, PURGE_RXABORT|PURGE_RXCLEAR|PURGE_TXABORT|PURGE_TXCLEAR );
    SetCommMask(m_ComHandle,m_dwEvtMask);//m_dwEvtMask定义为EV_RXCHAR 
    //(1):
    void CComm::SetDCB()
    {
    m_dwEvtMask=0;
    Init_OVERLAPPEN();
    ///////////////////////////////
    GetCommState(m_ComHandle,&m_Dcb);
    m_Dcb.BaudRate=9600;
    m_Dcb.ByteSize=8;
    m_Dcb.Parity=NOPARITY;
    m_Dcb.StopBits=TWOSTOPBITS;
    m_Dcb.fRtsControl = RTS_CONTROL_ENABLE;
    if (!SetCommState(m_ComHandle,&m_Dcb))
    {
    DWORD err=GetLastError();
    GetError(err);
    AfxMessageBox("SetDcb error!");
    }
    }bool CComm::Init_OVERLAPPEN()//m_osRead和m_osWrite为类成员,
                                //g_Event[4]和sum为全局static变量,
    {
    //memset m_osRead.Internal=5000;
    m_osRead.InternalHigh=1000;   
    m_osRead.Offset=5000;
    m_osRead.OffsetHigh=5000;
    if((m_osRead.hEvent = CreateEvent(NULL,false,false,NULL))==NULL)
    {
    return false;
    AfxMessageBox("createeventR error!");
    }
    event[g_sum]=m_osRead.hEvent;
    //ResetEvent(
    g_sum++;
    m_osWrite.Internal=5000;
    m_osWrite.InternalHigh=5000;
    m_osWrite.Offset=5000;
    m_osWrite.OffsetHigh=5000;
    if((m_osWrite.hEvent = CreateEvent(NULL,false,false,NULL))==NULL)
    {
    return false;
    AfxMessageBox("createeventW error!");
    }
    event[g_sum]=m_osWrite.hEvent;
    g_sum++;
    return true;

    }////////////////////////////////////////
    【不会停】
    for(;;){
    E=WaitForMultipleObjects(4,event,false,INFINITE);
    if(E!=0)
         comX.ReadCombuf(p,q);
    else
    {
               ……
    }//comX.GetError(GetLastError());
    }
      

  5.   

    没时间看你的程式用我代码我想应可以解决所有的东西都不要改
    // 以默认方式初始化串口
    void CSaimIO::InitaiseIO()
    {
    IoInfoData.idComDev = 0 ;
    IoInfoData.bByteSize = 8 ;
    IoInfoData.fConnected = FALSE; 
    IoInfoData.bPort = 1 ;
    IoInfoData.dwBaudRate  = CBR_9600;
    IoInfoData.bFlowCtrl = FALSE; //FC_XONXOFF; //  FC_RTSCTS; //FC_XONXOFF;
    IoInfoData.fXonXoff = 0 ;
    IoInfoData.bParity = NOPARITY; // EVENPARITY ;MARKPARITY ; SPACEPARITY; ODDPARITY;
    IoInfoData.bStopBits = ONESTOPBIT;  //ONE5STOPBITS; TWOSTOPBITS
    IoInfoData.osWrite.Offset = 0;
    IoInfoData.osWrite.OffsetHigh = 0;
    IoInfoData.osRead.Offset = 0;
    IoInfoData.osRead.OffsetHigh = 0;
    IoInfoData.osRead.hEvent = NULL;
    IoInfoData.osWrite.hEvent = NULL;
    }
    //  Connect IO before use it.
    //  打开串开
    BOOL CSaimIO::Connect()
    {
       BOOL       fRetVal ;
       BYTE       bSet ;
       DCB        dcb ;
       char       szPort[10];   memset(szPort,0,10);   wsprintf(szPort,"COM%d:",IoInfoData.bPort);
       IoInfoData.idComDev = CreateFile(szPort,GENERIC_READ|GENERIC_WRITE,
                                    0,
                    NULL,
                    OPEN_EXISTING,
                    FILE_ATTRIBUTE_NORMAL|FILE_FLAG_OVERLAPPED,
                    NULL);   if( !IoInfoData.idComDev )
          return FALSE;   if(!SetCommMask(IoInfoData.idComDev,EV_RXFLAG)) // EV_RXCHAR))
      return FALSE;   // Alloc the buffer for Read and Write.
       if( SetupComm(IoInfoData.idComDev,4096,4096) == 0 )
          return FALSE;
       //Setup for overlapped I/O
       COMMTIMEOUTS CommTimesOuts;   if( IoInfoData.dwBaudRate == CBR_2400  ||
       IoInfoData.dwBaudRate == CBR_1200  ||
       IoInfoData.dwBaudRate == CBR_300   ||
       IoInfoData.dwBaudRate == CBR_110 )
       {
           // 读取溢出时间 = 要读取的字节 * 放大因子 + 固定时间
       // Bin 码每个BIN 间的时间允许为 30 ms , 在此设定为 50 ms , 超过该时间说明读取完成
       CommTimesOuts.ReadIntervalTimeout = 50;
       // 时间放大因子
       CommTimesOuts.ReadTotalTimeoutMultiplier = 10 ;
       // 固定时间,  
       CommTimesOuts.ReadTotalTimeoutConstant = 1000 ;   }
       else
       {
       // 读取溢出时间 = 要读取的字节 * 放大因子 + 固定时间
       // Bin 码每个BIN 间的时间允许为 30 ms , 在此设定为 100 ms , 超过该时间说明读取完成
       CommTimesOuts.ReadIntervalTimeout = 30;
       // 时间放大因子
       CommTimesOuts.ReadTotalTimeoutMultiplier = 8 ;
       // 固定时间,  
       CommTimesOuts.ReadTotalTimeoutConstant = 100 ;
       }       // 写数据溢出时间 = 要写入的字节 * 放大因子 + 固定时间
       CommTimesOuts.WriteTotalTimeoutMultiplier = 2*CBR_9600 / IoInfoData.dwBaudRate ;
       CommTimesOuts.WriteTotalTimeoutConstant = 50;   SetCommTimeouts(IoInfoData.idComDev,&CommTimesOuts);
       // Initise the com port.
       dcb.DCBlength = sizeof( DCB ) ;   GetCommState( IoInfoData.idComDev, &dcb ) ;   dcb.BaudRate = IoInfoData.dwBaudRate ;
       dcb.ByteSize = IoInfoData.bByteSize ;
       dcb.Parity = IoInfoData.bParity ;
       dcb.StopBits = IoInfoData.bStopBits ;   // setup hardware flow control   bSet = (BYTE) ((FC_RTSCTS & FC_DTRDSR) != 0) ;
       dcb.fOutxDsrFlow = bSet ;   dcb.fDtrControl = DTR_CONTROL_DISABLE ;   //给予提供电源 ,新的 485 就不需要提供
       dcb.fRtsControl = RTS_CONTROL_ENABLE ;   bSet = (BYTE) FC_RTSCTS ;
       dcb.fOutxCtsFlow = bSet ;
       // setup software flow control   bSet = (BYTE)  FC_XONXOFF ;   dcb.fInX = dcb.fOutX = bSet ;
       dcb.XonChar = ASCII_XON ;
       dcb.XoffChar = ASCII_XOFF ;
       dcb.XonLim = 100 ;
       dcb.XoffLim = 100 ;   // other various settings   dcb.fBinary = TRUE ;
       dcb.fParity = 1 ;  // Enalble Parity   fRetVal = SetCommState( IoInfoData.idComDev, &dcb ) ;   if( fRetVal != FALSE )
       IoInfoData.fConnected = TRUE;
       else
       return fRetVal;   //Ceate I/O event used for overlapped reads / writes
       IoInfoData.osRead.hEvent = CreateEvent( NULL ,   //no security
                                           TRUE ,   //explicit reset req
       FALSE ,  //initial event reset
       NULL);   //no name   if( IoInfoData.osRead.hEvent == NULL )
       {
       return FALSE;
       }   IoInfoData.osWrite.hEvent = CreateEvent( NULL ,   //no security
                                            TRUE ,   //explicit reset req
        FALSE ,  //initial event reset
        NULL);   //no name
       
       if( IoInfoData.osWrite.hEvent == NULL )
       {
       CloseHandle( IoInfoData.osRead.hEvent );
       return FALSE;
       }   // Clear Read and Send IO buffer
       if(PurgeComm(IoInfoData.idComDev,PURGE_RXCLEAR)== 0)
      return FALSE;
       if(PurgeComm(IoInfoData.idComDev,PURGE_TXCLEAR)== 0)
      return FALSE;   // Set The DataSet is ready TO Get Data
       EscapeCommFunction(IoInfoData.idComDev,SETDTR|SETRTS);   // Set Connected flag to TRUE
       IoInfoData.fConnected = TRUE ;     
       if( IoInfoData.dwBaudRate == CBR_4800  ||
       IoInfoData.dwBaudRate == CBR_2400  ||
       IoInfoData.dwBaudRate == CBR_1200  ||
       IoInfoData.dwBaudRate == CBR_300   ||
       IoInfoData.dwBaudRate == CBR_110 )
       {
       m_bHighSpeed = FALSE ;
      //BeginComProc();
       }
       else
       {
       m_bHighSpeed = TRUE ;
       }    //创建串口信号量
        if( !m_hComMutex )
    m_hComMutex = ::CreateMutex(NULL,FALSE,NULL);   return ( TRUE ) ;
    }
      

  6.   

    //  Send the Datas.
    //  写数据到串口
    BOOL CSaimIO::WriteToCom(unsigned char *lpCommand, DWORD dwBytesToWrite)
    {
       if (IoInfoData.fConnected == FALSE )
          return ( FALSE ) ;   //等到串口已可用
       if( m_hComMutex )
    ::WaitForSingleObject(m_hComMutex,INFINITE);   BOOL        fWriteStat ;
       DWORD       dwBytesWritten ;
       DWORD       dwErrorFlags;
       DWORD       dwError;
       DWORD       dwBytesSent=0;
       COMSTAT     ComStat;
       char        szError[ 128 ] ;   fWriteStat = WriteFile( IoInfoData.idComDev , lpCommand, dwBytesToWrite,
                               &dwBytesWritten,NULL) ; // &IoInfoData.osWrite ) ;   if(dwBytesWritten != dwBytesToWrite)
       return FALSE;   if (!fWriteStat)
       {
          if(GetLastError() == ERROR_IO_PENDING)
          {
             while(!GetOverlappedResult( IoInfoData.idComDev ,
                &IoInfoData.osWrite, &dwBytesWritten, TRUE ))
             {
                dwError = GetLastError();
                if(dwError == ERROR_IO_INCOMPLETE)
                {
                   // normal result if not finished
                   dwBytesSent += dwBytesWritten;
                   continue;
                }
                else
                {
                   // an error occurred, try to recover
                   wsprintf( szError, "向串口发送数据出错,错误代码: %u", dwError ) ;               MessageBox(NULL,szError,"发送数据出错",MB_ICONEXCLAMATION);               ClearCommError( IoInfoData.idComDev , &dwErrorFlags, &ComStat ) ;
                   
                   break;
                }
             }
          }
          else
          {
             // some other error occurred
             ClearCommError( IoInfoData.idComDev , &dwErrorFlags, &ComStat ) ;  if (dwErrorFlags > 0)
     {
     wsprintf( szError, "向串口发送数据出错,错误代码: %u", dwErrorFlags ) ;  MessageBox(NULL,szError,"发送数据出错",MB_ICONEXCLAMATION);
     }    //完成使用串口,释放串口
       ::ReleaseMutex(m_hComMutex);
           return ( FALSE );
          }
       }   //完成使用串口,释放串口
       if( m_hComMutex )
    ::ReleaseMutex(m_hComMutex);   return ( TRUE ) ;}//  Read the Datas.
    //  从串口中读出数据,DataBuffer 接收缓冲, DataLength 要接收的数据长度
    DWORD CSaimIO::GetData(unsigned char *DataBuffer, DWORD DataLength)
    {
    if (IoInfoData.fConnected == FALSE)
      return ( FALSE ) ; //等到串口已可用
    if( m_hComMutex )
    ::WaitForSingleObject(m_hComMutex,INFINITE); BOOL       fReadStat ;
    COMSTAT    ComStat ;
    DWORD      dwErrorFlags;
    DWORD      dwLength = DataLength;
    DWORD      dwError;
    char       szError[ 128 ] ; // only try to read number of bytes in queue
    ClearCommError( IoInfoData.idComDev, &dwErrorFlags, &ComStat ) ;
    //dwLength = min( DataLength, ComStat.cbInQue ) ;
    //和下面的 ReadFile( ...  dwLength,&dwLength, ...); 对应
    //读出串口中已有的数据但不等待还没有收到的数据
    //适用于读出不完整的数据到缓冲中,其它部分来完成数据拼合和清空
    if( ComStat.cbInQue == 0 )
    {
    //完成使用串口,释放串口
    if( m_hComMutex )
    ::ReleaseMutex(m_hComMutex);
    return 0 ;
    } if (dwLength > 0)
    {
    //读出串口中的已有的数据
    //fReadStat = ReadFile( IoInfoData.idComDev, DataBuffer,
    //                     dwLength, &dwLength, &IoInfoData.osRead ); //读出指定的数据,在指定的溢出时间内如果没有读出则只读出串口中已存在的数据
    fReadStat = ReadFile( IoInfoData.idComDev, DataBuffer,
    DataLength, &dwLength, &IoInfoData.osRead );
    if (!fReadStat)
    {
    if (GetLastError() == ERROR_IO_PENDING)
    {
    // We have to wait for read to complete.
    // This function will timeout according to the
    // CommTimeOuts.ReadTotalTimeoutConstant variable
    // Every time it times out, check for port errors
    while(!GetOverlappedResult( IoInfoData.idComDev,
       &IoInfoData.osRead, &dwLength, TRUE ))
    {
       dwError = GetLastError();
       if(dwError == ERROR_IO_INCOMPLETE)
      // normal result if not finished
      continue;
       else
       {
      // an error occurred, try to recover
      wsprintf( szError, "向串口读出数据出错,错误代码: %u", dwError ) ;   MessageBox(NULL,szError,"读出数据出错",MB_ICONEXCLAMATION);   ClearCommError( IoInfoData.idComDev, &dwErrorFlags, &ComStat ) ;
      if (dwErrorFlags > 0)
      {
    wsprintf( szError, "向串口读出数据出错,错误代码: %u", dwError ) ; MessageBox(NULL,szError,"读出数据出错",MB_ICONEXCLAMATION);
      }
      break;
       }
    }
    }
    else
    {
    // some other error occurred
    dwLength = 0 ;
    ClearCommError( IoInfoData.idComDev, &dwErrorFlags, &ComStat ) ;
    if (dwErrorFlags > 0 )
    {
     wsprintf( szError, "向串口读出数据出错,错误代码: %u", dwErrorFlags ) ;  MessageBox(NULL,szError,"读出数据出错",MB_ICONEXCLAMATION);            
    }
    }
    }
    } //完成使用串口,释放串口
    if( m_hComMutex )
    ::ReleaseMutex(m_hComMutex);
    return ( dwLength ) ;
    }读出串口的数据长度部分还可以修改一下
    老本都给你了不给分就?????
      

  7.   

    这位大哥请到:
    http://www.ht.com.cn/download/moxa/pcommpro/pcommpro.htm
      

  8.   

    我觉得你应该在
    DWORD SE = WaitForMultipleObjects(3,g_Event,false,INFINITE);//INFINITE 如果没有事件一直等待
    之前加上
    BOOL bResult;
    DWORD Event;
    bResult=WaitCommEvent(m_hCom,&Event,&m_overlappedRead);//如果有你的SetCommMask(..)设的事件,WaitCommEvent 会把m_overlappedRead 的hEvent 复位为信号状态,否则为非信号状态.
      

  9.   

    解决了,难为各位了,程序因为定义了一个全局的static变量,在主线程和辅线程中会变成两个,主辅线程各操纵一个,所以到WaitForMultipleObjects(3,g_Event,false,INFINITE)时g_Event虽然在主线程中附了值,现在却是NULL
    所以停不下来。感谢各位提供的帮助,分数嘛,只有平均分配了。