Интересно, что ты делаешь такое с портом, что GUI "фризится"? У меня все пашет, причем из-за гуя иногда слетает синхронизация.
Суть в том, что в винде при использовании overlapped операций приходится дожидаться их завершения, чтобы узнать сколько реально байт передалось/принялось
Например код при записи в порт:
C++ (Qt)
qint64 WinSerialPortEngine::write(const char *data, qint64 len)
{
...
DWORD writeBytes = 0;
bool sucessResult = false;
if (::WriteFile(m_descriptor, data, len, &writeBytes, &m_ovWrite))
sucessResult = true;
else {
if (::GetLastError() == ERROR_IO_PENDING) {
if (::GetOverlappedResult(m_descriptor, &m_ovWrite, &writeBytes, true))
sucessResult = true;
}
}
...
...
return quint64(writeBytes);
}
Вызывает тормоза на GetOverlappedResult() и тем они сильнее,
чем больший поток байт len мы передаем (проверено экспериментально).
Положительный момент этого метода в том, что после этого мы можем получить
реальное кол-во отправленых байт writeBytes.
В принципе, для операции записи я могу победить это - не дожидаясь
пока все байты отправятся и пока я получу writeBytes, т.е.
могу тупо сразу возвращать не writeBytes, а len.
Т.е. метод WinSerialPortEngine::write возвратит сразу такое кол-во
байт, которое было в него задано, т.е. "фейк"
В принципе, я щитаю, что это выход для метода write.
Теперь рассмотрим метод read(), в котором используется таже
конструкция:
C++ (Qt)
qint64 WinSerialPortEngine::read(char *data, qint64 len)
{
...
DWORD readBytes = 0;
bool sucessResult = false;
if (::ReadFile(m_descriptor, data, len, &readBytes, &m_ovRead))
sucessResult = true;
else {
if (::GetLastError() == ERROR_IO_PENDING) {
if (::GetOverlappedResult(m_descriptor, &m_ovRead, &readBytes, true))
sucessResult = true;
}
}
...
return qint64(readBytes);
}
Но тут надо уточнить, что читаем мы данные, которые уже доступны для чтения в UART-е,
поэтому, теоретически ReadFile должен сразу их вернуть, т.е. не должно быть
состояния ERROR_IO_PENDING. Но, я не уверен что его не будет,
подозреваю, что все-таки иногда будет выполняться ветка GetOverlappedResult(),
что будет приводить к тормозам. В принципе, это можно попробовать проверить
экспериментально, сунуть сюда отладочный вывод..
Сейчас основные тормоза в Windows из-за операции write() с ожиданием,
т.е. как показано в коде в самом верху.
Так вот вопрос: а в *nix операции write/read сразу возвращают управление или нет?
(даже если дескриптор сконфигурен как неблокирующий и таймауты везде стоят по-нулям).
Если сразу - то я не буду заморачиваться с асинхронным I/O, и просто немного
подкорректирую Windows часть, в части операции write().
Как-то так...
Мож у кого есть что получше предложить? Прокомментировать?