Domanda

La mia applicazione non riceve correttamente i dati dalla porta COM. Questo utilizzato per lavoro. Non so cosa sia successo. So che i dati appropriati vengono inviati / ricevuti sulla linea perché posso vedere sul mio analizzatore di protocollo.

Il PC ottiene nello stato WAIT_OBJECT_0 + 1, ma il contenuto del buffer sono sempre zero. So che questo è molto, ma se qualcuno può indicare quello che sto facendo male, sarei davvero grato. Posso aggiungere / rimuovere i dettagli come richiesto. Grazie.

EDIT: Ulteriori informazioni

Sono stato in grado di verificare che il PC effettua la chiamata a ReadFileEx, ed è "riesce". Tuttavia, il PC non viene mai in FileIOCompletionRoutine. Qualche idea? (Ho rimosso il di gestione degli errori dal codice per rendere la vita più semplice.) Inoltre, da quanto ho letto sul sito MSDN, sembra che FileIOCompletionRoutine verrà chiamato in modo asincrono nel proprio thread. È corretto? Grazie.

EDIT: Soluzione finale

Questo è quello che mi è venuta. Ovviamente, il codice di inizializzazione e di gestione degli errori non è qui. Non possiamo fare le cose troppo facili. :)

// Load event handles.
pHandles[0] = s_hSerialPortRxThreadExitEvent;
// OVERLAPPED structure event handle is loaded in loop.

while ( blContinue )
{
    // Wait for a communications event.
    if ( !::WaitCommEvent( s_hSerialPort, &dwEventMask, &s_ov ) )
    {
        if ( ::GetLastError() != ERROR_IO_PENDING )
        {
            blContinue = FALSE;
            continue;
        }
        else if ( ::WaitForSingleObject( pHandles[0], 0 ) == WAIT_OBJECT_0 )
        {
            // The thread-exit event has been signaled.  Get out of here.
            blContinue = FALSE;
            continue;
        }
    }
    else
    {
        // Load OVERLAPPED structure event handle.
        pHandles[1] = s_ov.hEvent;
    }

    if ( dwEventMask & EV_RXCHAR )
    {
        if ( !::ReadFile( s_hSerialPort, pBuf, RX_BUF_SIZE, NULL, &s_ov ) )
        {
            if ( ::GetLastError() == ERROR_IO_PENDING )
            {
                // Wait for events.
                dwObjectWaitState = ::WaitForMultipleObjects( 2, pHandles, FALSE, INFINITE );

                // Switch on event.
                switch ( dwObjectWaitState )
                {
                case WAIT_OBJECT_0:             // thread exit event signaled
                    blContinue = FALSE;
                    continue;

                case WAIT_OBJECT_0 + 1:         // OVERLAPPED structure event signalled
                    // Reset event first to mitigate underrun condition.
                    if ( !::ResetEvent( pHandles[1] ) )
                    {
                        blContinue = FALSE;
                        continue;
                    }

                    // Get the OVERLAPPED result.
                    if ( !::GetOverlappedResult( s_hSerialPort, &s_ov, &dwBytesRead, FALSE ) )
                    {
                        blContinue = FALSE;
                        continue;
                    }
                    break;

                default:                        // Error
                    blContinue = FALSE;
                    continue;
                }
            }
        }
        else if ( !::GetOverlappedResult( s_hSerialPort, &s_ov, &dwBytesRead, FALSE ) )
        {
            blContinue = FALSE;
            continue;
        }

        // If bytes were read...
        if ( dwBytesRead > 0 )
        {
            // Copy received data from local buffer to thread-safe serial port buffer.
            ::EnterCriticalSection( &s_csRxRingBuffer );
            blSuccess = s_pobjRxRingBuffer->Add( pBuf, dwBytesRead, TRUE );
            ::LeaveCriticalSection( &s_csRxRingBuffer );

            if ( !blSuccess )
            {
                blContinue = FALSE;
                continue;
            }

            // Set the received data event.
            if ( !::SetEvent( s_phEventIds[RECEIVE_EVENT] ) )
            {
                blContinue = FALSE;
                continue;
            }
        }
    }

    if ( dwEventMask & EV_TXEMPTY )
    {
        // Set the transmit complete event.
        if ( !::SetEvent( s_phEventIds[TRANSMIT_EVENT] ) )
        {
            blContinue = FALSE;
            continue;
        }
    }

} // end while ( blContinue );
È stato utile?

Soluzione

Non so se vedo il vostro sbagliato codice, ma vedo che si sta configurando evento, e in attesa per l'evento senza dire la O / S che cosa stai aspettando, si dovrebbe fare ReadFileEx () prima di raccontare O / S si è in attesa per l'evento quando c'è dati nel buffer di leggere, poi si fa WFSO () / WFMO (), questo quello che faccio sulla mia libreria porta seriale (sul filo ricevitore):

do
{
    byteRead = 0;
    readBuffer = 0;
    if(!::ReadFile(this->commHandle,&readBuffer,
                   1,NULL,&this->readOverlapIO))
    {
         if(GetLastError() == ERROR_IO_PENDING)
         {
             if(::WaitForSingleObject(this->readOverlapIO.hEvent,INFINITE) == WAIT_OBJECT_0)
             {
                 if(!::GetOverlappedResult(this->commHandle,&this->readOverlapIO,&byteRead,FALSE))
                 {
                     byteRead = 0;
                 }
             }
         }
    }
    else
    {
         if(!::GetOverlappedResult(this->commHandle,&this->readOverlapIO,&byteRead,FALSE))
         {
              byteRead = 0;
         }
    }
    if(byteRead > 0)
    {
          totalByteRead += this->ringBuffer.push(readBuffer,1);
    }
}while(byteRead);

Io uso evento di completamento utilizzando il segnale evento qui, è possibile modificarlo in funzione di completamento se si voleva.

Altri suggerimenti

Inoltre, da quello che ho letto su MSDN sito web, sembra che FileIOCompletionRoutine otterrà chiamato in modo asincrono nel proprio filo. E 'corretto?

No, che non è corretto. La routine di completamento viene chiamata nel contesto della filettatura in cui la ReadFileEx chiamata viene effettuata. Quando è pronto per l'esecuzione, si è in coda fino a quando il thread è in uno "stato di attesa alertable". Questo accade di solito quando si chiama una delle Wait * funzioni. Inoltre, da MSDN per ReadFileEx , essa afferma:

La funzione ignora il ReadFileEx membro hEvent di struttura OVERLAPPED. Una domanda è libero di utilizzare tale membro per i propri scopi in contesto di una chiamata ReadFileEx. ReadFileEx segnala completamento della sua operazione di lettura telefonando, o fare la coda una chiamata per la routine di completamento puntato da lpCompletionRoutine, così non ha bisogno di un manico evento.

Quindi, l'evento si è creato non ha alcun effetto. Inoltre, la legge non saranno trattati fino ReadFileEx è chiamata, in modo da avere per invertire l'ordine con la vostra attesa. Che cosa si dovrebbe fare nel vostro ciclo di lettura è qualcosa di simile (in pseudocodice):

while(continue)
{
    ReadFileEx();
    WaitForSingleObject(s_hSerialPortRxThreadExitEvent);
    . . . etc . . .
}

se sei sicuro che qualcosa (dovrebbe) sono stati ricevuti, quindi può è il doppio uso di & dwWritten. Provare a utilizzare due variabili separate (una per ReadFile e un altro per GetOverlappedResult). Controllare entrambi, naturalmente.

Inoltre, avete inizializzato la struttura sovrapposta completa a 0 di (beffore assegnando l'evento ad esso)?

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top