Я пишу класс для COM-портов в C ++, используя win-api.Прямо сейчас я тестирую функциональность на RS232 с подключенными выводами Rx и Tx.
Я столкнулся с несколько странной проблемой.Я использую отдельный поток для чтения из COM-порта.В потоке я использую SetCommMask
, WaitCommEvent
и WaitForSingleObject
для ожидания поступления символа в буфер.Однако WaitForSingleObject
имеет тенденцию выходить без фактического получения символов.
Я предположил, что это было вызвано неправильным использованием упомянутых функций, но потом я обнаружил, что преждевременный выход не происходит каждый раз (первый раз всегда работаеткак предполагалось).
Во втором цикле поток переходит в состояние ожидания и через некоторое время завершает работу, переходя к ReadFile
, где он ожидает бесконечно, поскольку буфер пуст, данные не должны отправляться, и общее время ожидания не используется.
Мне уже советовали просто использовать ReadFile
и обрабатывать только те данные, которые я получаю, однако я использую другой поток, чтобы проверить, был ли отключен канал связи, и сейчас мне нужно различать ожиданиеданные и чтение данных.
Вызов ClearCommError
для проверки входного буфера с ReadFile
не вариант, потому что в таком случае InQue
всегда равен 0. Поэтому я не могу сказать, действительно ли ReadFile
читает или ждет.
//following code runs in separate thread
DWORD dwEventMask1, dwEventMask2, LastError, Status;
OVERLAPPED Overlapped; HANDLE Serial_Port_Handle;
std::string stringBuffer("");
const size_t ReadBufferLength = 256;
char tempBuffer[ReadBufferLength];
GetCommMask(Serial_Port_Handle, &dwEventMask1);
if (dwEventMask1) // Before starting the thread I check the state of Input Buffer with GetCommError().
{ // If Buffer is not empty, CommMask is set to 0 signaling there is no need for waiting.
Overlapped.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
//wait for comm event
if (!WaitCommEvent(Serial_Port_Handle, &dwEventMask1, &Overlapped))
{
if ((LastError = GetLastError()) == ERROR_IO_PENDING)
{
Waiting = true; //signal bool for synchronization purposes
if ((Status = WaitForSingleObject(Overlapped.hEvent, INFINITE)) == WAIT_OBJECT_0)
{
GetCommMask(Serial_Port_Handle, &dwEventMask2);
Waiting = false;
CloseHandle(Overlapped.hEvent);
// I close handle and set all members of Overlapped struct to 0
}
if (dwEventMask2 !== dwEventMask1) // check if wait have not exited because of SetCommMast()
return;
}
}
}
do // this loop reads from input buffer until empty
{
Overlapped.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);//set up read overlapped operation
if (ReadFile(Serial_Port_Handle, tempBuffer, ReadBufferLength - 1, &NoBytesRead, &Overlapped)) //start read opperation
{ //Read operation done on 1 go
GetOverlappedResult(Serial_Port_Handle, &Overlapped, &NoBytesRead, FALSE); //get NoBytesRead
CloseHandle(Overlapped.hEvent)
stringBuffer.append(tempBuffer, (size_t) NoBytesRead); // save read data
}
else if ((LastError = GetLastError()) == ERROR_IO_PENDING) //operation not yet complete
{
GetOverlappedResult(Serial_Port_Handle, &Overlapped, &NoBytesRead, TRUE); // wait for completion
stringBuffer.append(tempBuffer, (size_t)NoBytesRead);
}
else
{
CloseHandle(Overlapped.hEvent)
return;
}
} while ((NoBytesRead == (ReadBufferLength - 1)) && NoBytesRead);
// Loop runs while tempBuffer's full capacity is used.
// I realize that since I don't use Total Timeout there is a possibility
// of the loop getting stuck. If you can suggest other solution than using
// Total Timeout or use GetCommError() to get input buffer state, please do so.
return;
Этот код несколько упрощен (проверка возвращаемых значений и т. Д.).
1) Кто-нибудь из вас сталкивался с таким поведением?
2) Я используюПЕРЕКРЫТЫЕ операции в коде.После завершения операции я всегда использую CloseHandle
и повторно инициализирую структуру OVERLAPPED, прежде чем использовать ее для другой операции.Это правильно или сброса структуры достаточно?