Как я могу проверить, пуст ли входной буфер?

Я пытаюсь написать простой класс для работы с последовательным портом в Windows, используя стандартную библиотеку Windows.

Мне нужно проверить, пуст ли входной буфер.

До сих пор я пытался использовать SetCommEvent с опцией EV_RXCHAR, однако этот метод не работает. Функция, кажется, ждет прибытия нового символа. Если бы я попытался отправить char, заснуть на секунду и применить это, функция не вернулась бы - она ​​продолжает ждать.

bool isEmpty()
{
    DWORD dwEventMask = 0;
    DWORD Status = 0;

    if (CheckAsyncRead())
        return false;

    if (!SetCommMask(hPort, EV_RXCHAR)) //wait for char receival
        std::cout << "Error in creating Overlapped event" << std::endl;

    osReader.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);

    if (WaitCommEvent(hPort, &dwEventMask, &osReader))
    {
                //close event handle
        return false;
    }

    Status = WaitForSingleObject(osReader.hEvent, 10);

        //I wait for 10 ms in case the function doesn't return immediately
    //Close event handle

    if (Status == WAIT_OBJECT_0)
    {
        return false;
    }
    else
        return true;

}

Я надеялся, что WaitCommEvent или WaitForSingleObject вернутся, если в буфере присутствуют какие-либо символы, но этого не происходит, если между получением символа и вызовом функции ожидания есть более длительная пауза.

Вы звоните SetCommTimeouts? С какими ценностями?

Ben Voigt 08.04.2019 16:36

да. Сейчас у меня следующие настройки: ReadIntervalTimeout = 2; ReadTotalTimeoutConstant = 0; tReadTotalTimeoutMultiplier = 0; WriteTotalTimeoutConstant = 0; WriteTotalTimeoutMultiplier = 3;

Radek Hlavinka 11.04.2019 18:26
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
0
2
644
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Вы можете использовать ЧитатьФайл() с дескриптором, открытым с помощью СоздатьФайл() с флагом FILE_FLAG_OVERLAPPED. Если функции ReadFile() нечего возвращать, она вернет последнюю ошибку ERROR_IO_PENDING, что означает, что ваш буфер в настоящее время пуст.

Настройки тайм-аута также имеют значение. На самом деле имеют значение только настройки таймаута.

Ben Voigt 08.04.2019 16:36
Ответ принят как подходящий

Вы можете использовать Функция ClearCommError, чтобы узнать размер данных, хранящихся в буфере.

В результате вызова cbInQue из Структура КОМСТАТ, подлежащего уведомлению, имеет размер данных, хранящихся во входном буфере.

Спасибо. Именно то, что мне было нужно.

Radek Hlavinka 09.04.2019 00:12

Будьте осторожны, потому что ClearCommError() имеет побочные эффекты. Не относитесь к нему как к пассивному добытчику! (Эти побочные эффекты являются источником серьезной ошибки в классе .NET SerialPort.)

Ben Voigt 11.04.2019 19:00

@Ben Voigt, если есть подробная информация или ссылка о причине и мерах, пожалуйста, представьте.

kunif 12.04.2019 00:40

Побочные эффекты описаны на странице MSDN, на которую вы ссылаетесь.

Ben Voigt 12.04.2019 01:41

@Ben Voigt Является ли преждевременный возврат WaitCommEvent одним из этих побочных эффектов? Потому что я в настоящее время столкнулся с такой проблемой.

Radek Hlavinka 15.04.2019 14:05

@RadekHlavinka: Вы уверены, что не видите побочного эффекта SetCommMask? Документально подтверждено, что WaitCommEvent возвращается немедленно. Возможно, замешан ClearCommError, но, скорее всего, виновато задокументированное взаимодействие. Я имел в виду тот факт, что вся информация об ошибке очищается вызовом. Ошибка в .NET состоит в том, что два потока вызывают ClearCommError, один использует информацию об ошибке, другой использует длину входного буфера и отбрасывает ошибки.

Ben Voigt 15.04.2019 16:36

@Ben Voigt: я уверен. Я попытался выполнить код шаг за шагом и добавил простые маркеры к любому использованию SetCommEvent (простая запись в std::cout). Поток входит в состояние ожидания и через некоторое время выходит из него, переходя к ReadFile, где он ожидает бесконечно, потому что буфер пуст, данные не отправляются, и я не использую Total timeout. Что меня действительно озадачивает, так это то, что это появляется только во втором проходе потока - в 1-м проходе поток ожидает получения символа, как и предполагалось.

Radek Hlavinka 15.04.2019 17:06

@Radek Hlavinka, было бы лучше задать новый вопрос вместе с подробной информацией.

kunif 15.04.2019 17:14

@RadekHlavinka: Это SetCommMask, а не SetCommState (и я даже не вижу функции с именем SetCommEvent), которая прерывает WaitCommEvent.

Ben Voigt 15.04.2019 17:51

@RadekHlavinka: я бы все же предложил вам разработать свой класс, чтобы вам не нужно было спрашивать, сколько данных находится в буфере. Вместо этого просто получите все имеющиеся данные (установите нулевой общий тайм-аут чтения, как описано в COMMTIMEOUTS), а затем проверьте длину полученных данных. Даже если не считать побочных эффектов ClearCommError, длина полученного вами буфера устаревает еще до того, как функция вернется к вам, поэтому вы вынуждены совершить логическую ошибку TOCTOU.

Ben Voigt 15.04.2019 17:53

Я создал новый вопрос, в котором попытался лучше объяснить проблему (stackoverflow.com/questions/55697983/…). Также я не использую ClearCommError для получения количества данных во входном буфере, просто чтобы посмотреть, есть ли они.

Radek Hlavinka 16.04.2019 00:24

Другие вопросы по теме