Мое приложение использует отдельный поток для обработки полученных последовательных данных асинхронно. ПК попадает в приемник-получатель, как ожидалось, но оттуда все странно.Последовательный порт Получение темы не работает как ожидается - C++
Это моя функция потока:
// 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;
Если я могу установить точку останова на линии вызывающего ReadFile
все работает, как я ожидал, и компьютер получает в функцию обратного вызова. Однако, если я установил свою точку останова на следующей строке, где dwWritten
оценивается на ноль, она равна нулю, выражение оценивается как ИСТИНА, и цикл завершается; ПК никогда не попадает на обратный вызов. Что я делаю не так? Благодарю.
Похоже, вы делаете гораздо больше работы, чем вам нужно. Почему вы обрабатываете последовательные данные асинхронно в потоке? Почему бы просто не позволить потоку блокировать ввод-вывод? – Jay
Также вы пропустите ручку, вы не можете вернуться из функции, не закрывая ее, но вы делаете это при ошибках. – doron
Перед вызовом ReadFile вам необходимо сбросить событие pHandles [1]. –