CloseHandle () возвращает до того, как последовательный порт будет фактически закрыт - PullRequest
6 голосов
/ 17 января 2012

Я дергаю себя за волосы, пытаясь понять, когда завершается закрытие последовательного порта, чтобы я мог открыть его снова.Оказывается, CloseHandle() возвращается до того, как порт фактически разблокирован.

Я открываю последовательный порт, используя CreateFile(FILE_FLAG_OVERLAPPED), связываю его с CompletionPort, используя CreateIoCompletionPort(), читаю / пишу в него, используя * 1006.*, WriteFile() и закрывая его с помощью CloseHandle().

Я заметил, что если я закрою и снова открою последовательный порт достаточно быстро, я получу ERROR_ACCESS_DENIED обратно от CreateFile().Это происходит несмотря на то, что я жду возврата CloseHandle(), а затем ожидаю, когда все ожидающие операции чтения / записи, связанные с этим дескриптором, вернутся из порта завершения.Конечно, есть лучший способ:)

Как синхронно закрыть последовательный порт? Пожалуйста, не повторяйте петли, sleep () или некоторые другие дешевые хаки.

EDIT : Возможно, это как-то связано с моим использованием портов завершения и FILE_FLAG_OVERLAPPED.Я получаю обратный вызов, когда операции чтения / записи завершены.Есть ли какой-то обратный вызов для закрытия порта?

Ответы [ 3 ]

1 голос
/ 17 января 2012

Я считаю, что проблема с драйвером, который обслуживает COM-порт.Следовательно, не будет API для «фактического закрытия» COM-порта.

Кстати, после закрытия дескриптора файла не нужно ждать завершения всех выдающихся операций ввода-вывода с ошибками.Когда CloseHandle возвращает все ожидающие операции ввода-вывода уже завершено / отменено, вы просто получаете обратные вызовы асинхронно (будь то через порт завершения или очередь APC, неважно).

В частности, драйверы FTDI (те, которые эмулируют COM-> USB), как известно, очень сбивают с толку.

Я могу только рекомендовать попробовать сброс данных перед закрытием ручки.Вы можете подождать, пока все операции ввода-вывода завершат , прежде чем закроет COM-порт (если это применимо для вашего случая).В качестве альтернативы вы можете позвонить SetCommMask и WaitCommEvent, чтобы убедиться в отсутствии ожидающих отправки данных.Надеемся, что это может помочь.

РЕДАКТИРОВАТЬ:

Немедленно (до возвращения) CloseHandle отменяет все ожидающие операции ввода-вывода для дескриптора файла?

Строго говоря - нет .

Могут быть и другие ссылки на файловый объект.Например, код режима пользователя может вызвать DuplicateHandle, или драйвер режима ядра может вызвать ObReferenceObjectByXXXX.В таком случае объект, на который ссылается дескриптор, не обязательно освобождается.

Когда последний дескриптор закрыт, вызывается драйвер DispatchCleanup.Он должен отменить все ожидающие операции ввода-вывода в соответствии с this .

Однако, пока один поток находится в пределах CloseHandle - теоретически вы можете выполнить другой ввод-вывод из другого потока (если выповезло - ручка все равно будет в силе).Во время вызова функции ввода-вывода (например, WriteFile или т. Д.) ОС временно увеличивает счетчик ссылок на объект.Это, в свою очередь, может запустить другой ввод / вывод, который не будет отменен напрямую с помощью вызова CloseHandle.

Однако в этом случае дескриптор будет закрыт O / S сразу после нового ввода / вывода.O выдан, потому что счетчик ссылок на объект снова достиг 0. 0. 1041 *

Так что в таком извращенном сценарии может возникнуть ситуация, когда сразу после вызова CloseHandle вы не сможете открыть файл заново.еще раз.

0 голосов
/ 06 июля 2016

Когда вы открываете COM-порт в потоке, операционная система открывает другой скрытый поток для выполнения операций ввода-вывода. Я пытаюсь решить закрытие порта, а также. Насколько я могу сказать, один метод, который может работать: 1) приостановить поток, который открыл COM-порт, 2) PurgeComm (), чтобы остановить все операции ввода-вывода и очистить все буферы ввода / вывода для чтения / записи, и 3) затем попытаться закрыть COM-порт. Может быть задействован объект waitforsingle, чтобы определить, когда поток с COM-портом фактически приостанавливается. Если COM-порт не нужно обязательно закрывать, я рассматриваю возможность оставить COM-порт открытым и позволить WinProc обработать команду IDM_Exit для закрытия COM-порта, потоков и приложения. Не то, что я хотел, а вариант, с которым я мог бы жить. Я использую соединение USB с последовательным портом и не уверен, какие проблемы это вызывает у меня. Я знаю, что если вы используете интерфейс USB к последовательному порту, вам нужно установить высокий 20-контактный вывод (DTR). Контакт 20 помогает питать интерфейс, но обеспечивает только около 30 мА или около того. Если все это работает, я сделаю обновление к этому сообщению и сообщу, как, если я смог закрыть COM-порт. Windows запуталась в драйвере последовательного порта и, похоже, довольствуется тем, что оставляет беспорядок!

0 голосов
/ 20 сентября 2012

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

...