Отменить WaitCommEvent для перекрывающегося последовательного ввода-вывода

Я работаю с нестандартным модемом через последовательный порт с перекрытием. Помимо чтения и записи в телекоммуникационную линию, я должен проверить линии управления, такие как CTS и DSR, используя файл WaitCommEvent().

DWORD EvtMask;
/// (some scopes/levels ommitted)

const BOOL syncChange = WaitComEvent(hFile, &EvtMask, &overlapped);
if (!syncChange) {
    assert(GetLastError() == ERROR_IO_PENDING);
    /// *background activity* probably writing into EvtMask
    /// until overlapped.hEvent gets signalled
}

В (практически во всех) случаях вызов функции указывает на *background activity*, я должен ждать, пока произойдет overlapped.hEvent. Поскольку я также ожидаю событий из альтернативных источников (например, IPC, вызванный пользовательским вводом, завершение программы), я использую функцию WaitForMuiltipleObjects(). Но если ожидание блокировки завершено по другим причинам, кроме изменения контрольной строки, как я могу остановить фоновую активность на EvtMask? Код, на котором я основан, в настоящее время использует SetCommMask(hFile, 0), но я не нашел надежной ссылки для этого.

Я также наблюдаю случаи, когда изменения в линиях управления не поддерживаются должным образом (драйвер?, ВМ?), поэтому мне приходится выполнять нарезанное ожидание с промежуточной проверкой.

Что нужно сделать, чтобы безопасно покинуть область, в которой объявлена ​​переменная EvtMask?


person Wolf    schedule 22.09.2014    source источник
comment
Вы должны вызвать CancelIo(). Пользовательский ввод, как правило, не является веской причиной для отмены ввода-вывода. У вас есть китайское печенье с предсказанием, в котором говорится, что вы собираетесь полностью переписать это.   -  person Hans Passant    schedule 22.09.2014
comment
@HansPassant, ха-ха, многое нужно переписать...   -  person Wolf    schedule 22.09.2014
comment
@HansPassant Я изменил вопрос, есть еще одна (важная) причина, которую следует учитывать. Теперь это имеет для вас больше смысла? Спасибо!   -  person Wolf    schedule 10.10.2014
comment
@ Ханс: Нет, не знаешь.   -  person Ben Voigt    schedule 10.10.2014
comment
@BenVoigt, так что этот вопрос кажется вам актуальным?   -  person Wolf    schedule 10.10.2014


Ответы (1)


Код у вас правильный и полностью поддерживается документацией, что ясно говорит:

Если процесс пытается изменить маску события дескриптора устройства с помощью функции SetCommMask во время выполнения перекрывающейся операции WaitCommEvent, WaitCommEvent возвращается немедленно.

Я использовал этот факт как на «реальных» последовательных портах, так и на эмуляциях виртуальных последовательных портов USB, и он работает надежно.

(В моем конкретном случае я следил за EV_TXEMPTY, чтобы гарантировать минимальное разделение между определенными передачами по проводу)

person Ben Voigt    schedule 10.10.2014
comment
Хорошо, эта самая часть была непонятна для меня. Он смешивает вызовы WaitCommEvent и запуск операции в фоновом режиме. Тем не менее спасибо, что заглянули. И это определенно полезно :-) - person Wolf; 10.10.2014
comment
Маленькая деталь: после вызова SetCommMask с нулевой маской нужно ли еще раз вызывать WaitCommEvent? - person Wolf; 13.10.2014
comment
@Wolf: ожидающая операция WaitCommEvent завершится немедленно (или, по крайней мере, очень скоро - не думайте, что ваша память вернется, как только будет вызван SetCommMask). Поэтому, если вы хотите получать уведомления еще раз, вам нужно позвонить еще раз. - person Ben Voigt; 13.10.2014
comment
Если я использую нулевую маску, то, вероятно, реальных уведомлений не будет. Но вполне вероятно, что переменная, которую я использовал в вызове WaitCommEvent, все еще привязана. Разве я не должен позвонить GetOverlappedResult(..., TRUE)? - person Wolf; 15.10.2014
comment
@Wolf: Вы должны обрабатывать принудительное завершение так же, как и любое другое. Позвоните GetOverlappedResult и, если вас еще интересуют события, позвоните еще раз WaitCommEvent, иначе можете покончить с памятью. - person Ben Voigt; 15.10.2014