Meine Anwendung verwendet einen separaten Thread für die asynchrone Verarbeitung empfangener serieller Daten. Der PC gelangt wie erwartet in den Empfangs-Handler, aber von dort gehen die Dinge merkwürdig aus.Serieller Port empfängt Thread, der sich nicht erwartungsgemäß verhält - C++
Das ist meine Thread-Funktion:
// Create event for OVERLAPPED structure.
s_ov.hEvent = ::CreateEvent(
NULL, // No security
TRUE, // Create a manual-reset event object
FALSE, // Initial state is non-signaled
NULL // No name specified
);
// Load event handles.
pHandles[0] = s_hSerialPortRxThreadExitEvent;
while (bContinue)
{
if (!::WaitCommEvent(s_hSerialPort, &dwEventMask, &s_ov))
{
if (::GetLastError() != ERROR_IO_PENDING)
{
TRACE(_T("SerialPortRxThreadFn : Call to WaitCommEvent failed.\r\n\tError: %d\r\n\tFile: %s\r\n\tLine: %d\r\n"), ::GetLastError(), __WFILE__, __LINE__);
return ::GetLastError();
}
}
pHandles[1] = s_ov.hEvent;
dwObjectWaitState = ::WaitForMultipleObjects(2, pHandles, FALSE, INFINITE);
switch (dwObjectWaitState)
{
case WAIT_ABANDONED:
TRACE(_T("SerialPortRxThreadFn : Owner thread terminated prematurely.\r\n\tError: %d\r\n\tFile: %s\r\n\tLine: %d\r\n"), ERROR_ARENA_TRASHED, __WFILE__, __LINE__);
return ERROR_ARENA_TRASHED;
break;
case WAIT_TIMEOUT:
TRACE(_T("SerialPortRxThreadFn : The timeout is set to INFINITE; there should be no timeout. State is nonsignaled.\r\n\tError: %d\r\n\tFile: %s\r\n\tLine: %d\r\n"), WAIT_TIMEOUT, __WFILE__, __LINE__);
return WAIT_TIMEOUT;
break;
case WAIT_FAILED:
TRACE(_T("SerialPortRxThreadFn : Call to WaitCommEvent failed.\r\n\tError: %d\r\n\tFile: %s\r\n\tLine: %d\r\n"), ::GetLastError(), __WFILE__, __LINE__);
return ::GetLastError();
break;
case WAIT_OBJECT_0: // thread exit event signalled
bContinue = FALSE;
if (!::ResetEvent(pHandles[0]))
{
TRACE(_T("SerialPortRxThreadFn : Failed to reset the serial port thread exit event.\r\n\tError: %d\r\n\tFile: %s\r\n\tLine: %d\r\n"), ::GetLastError(), __WFILE__, __LINE__);
return ::GetLastError();
}
break;
case WAIT_OBJECT_0 + 1: // OVERLAPPED structure event signalled
// Read data from serial port.
if (!::ReadFile(s_hSerialPort, pBuf, RX_BUF_SIZE, &dwWritten, &s_ov)) // <- Set breakpoint here
{
TRACE(_T("SerialPortRxThreadFn : Call to ReadFile filed.\r\n\tError: %d\r\n\tFile: %s\r\n\tLine: %d\r\n"), ::GetLastError(), __WFILE__, __LINE__);
return ::GetLastError();
}
// Discontinue thread operation if there are no more bytes in the serial port receive buffer.
if (dwWritten == 0) // <- Or, set breakpoint here
{
bContinue = FALSE;
}
// Copy the received bytes to the thread-safe buffer.
else if (!s_pobjRxRingBuffer->Add(pBuf, dwWritten, TRUE))
{
TRACE(_T("SerialPortRxThreadFn : Failed to add bytes to ring buffer.\r\n\tError: %d\r\n\tFile: %s\r\n\tLine: %d\r\n"), ERROR_INSUFFICIENT_BUFFER, __WFILE__, __LINE__);
return ERROR_INSUFFICIENT_BUFFER;
}
else if (s_SpCallbackFn != NULL)
{
// Notify application of received data.
if ((dwRetVal = s_SpCallbackFn(s_pobjRxRingBuffer->ItemsInBuffer())) != ERROR_SUCCESS)
{
TRACE(_T("SerialPortRxThreadFn : Serial port callback function failed.\r\n\tError: %d\r\n\tFile: %s\r\n\tLine: %d\r\n"), dwRetVal, __WFILE__, __LINE__);
return dwRetVal;
}
}
if (!::ResetEvent(pHandles[1]))
{
TRACE(_T("SerialPortRxThreadFn : Failed to reset the OVERLAPPED structure event.\r\n\tError: %d\r\n\tFile: %s\r\n\tLine: %d\r\n"), ::GetLastError(), __WFILE__, __LINE__);
return ::GetLastError();
}
break;
default:
// Do nothing.
break;
}
}
::CloseHandle(s_ov.hEvent);
return ERROR_SUCCESS;
Wenn ich meinen Haltepunkt auf der Linie gesetzt Aufruf ReadFile
alles funktioniert, wie ich erwarte, und der PC wird in die Callback-Funktion. Wenn ich jedoch meinen Haltepunkt in der nächsten Zeile setze, wo dwWritten
für Null ausgewertet wird, ist es Null, der Ausdruck wird als WAHR ausgewertet, und die Schleife wird beendet; der PC kommt nie zum Rückruf. Was mache ich falsch? Vielen Dank.
Scheint so, als ob du viel mehr Arbeit machst, als du brauchst. Warum behandeln Sie serielle Daten asynchron in einem Thread? Warum lassen Sie nicht einfach den Thread auf I/O blockieren? – Jay
Sie verlieren auch den Handle, Sie können nicht von der Funktion zurückkehren, ohne den Handle zu schließen, aber Sie tun dies unter Fehlerbedingungen. – doron
Sie müssen das Ereignis pHandles [1] vor dem Aufruf von ReadFile zurücksetzen. –