Восстановление из выпадающего списка ComPort
D5-pro: использование TurboPower APro и компонентов ComPort и терминала с USB Arduino Nano для очень простого Comms-терминала. Все работает нормально, пока я не отключу USB для симуляции потери порта. Все просто зависает и не будет перезагружаться без закрытия и перезапуска.
Я не могу найти событие или процесс, который отслеживает состояние порта, поэтому я могу корректно закрыть порт. Я могу предотвратить открытие порта, если он не существует, но когда он открыт и данные передаются, я, похоже, теряю к нему доступ.
Я также попробовал TComPort и Terminal от Dejan Crnila, и он также не останавливается. Это на самом деле происходит сбой, и я должен использовать TaskManager, чтобы закрыть все это.
Может кто-нибудь, пожалуйста, сообщите мне некоторые фрагменты кода, которые могут указывать на отсутствие порта. Или есть лучший бесплатный компонент для этого.
1 ответ
Требуются некоторые модификации в модуле AwUser.
Добавьте новое событие для ошибок ввода / вывода.
TPortIOErrorEvent = процедура (CP: TObject; Ошибка: кардинальная) объекта; свойство OnPortIOError: TPortIOErrorEvent read FOnPortIOError write FOnPortIOError;
Измените метод TComThread.Execute в модуле AwUser.
{Release time slice until we get a communications event} if not WaitComEvent(CurrentEvent, @ComOL) then begin if GetLastError = ERROR_IO_PENDING then begin if GetOverLappedResult(CidEx, ComOL, Junk, True) then begin {WIN32 bug workaround: Apro gets the modem status bits with a call (later) to GetCommModemStatus. Unfortunately, that routine never seems to return either RI or TERI. So, we note either EV_RING or EV_RINGTE here and later manually merge the TERI bit into ModemStatus.} if ((CurrentEvent and EV_RINGTE) <> 0) or ((CurrentEvent and EV_RING) <> 0) then RingFlag := True; {Read complete, reset event} ResetEvent(ComOL.hEvent); end else begin {Port closed or other fatal condition, just exit the thread} SetEvent(GeneralEvent); CloseHandle(ComOL.hEvent); H.ThreadGone(Self); Exit; end; end else begin Err := GetLastError; {!!! added code} { If we get an ERROR_INVALID_PARAMETER, we assume it's our } { use of ev_RingTe -- clear the flag and try again } if (GetLastError = ERROR_INVALID_PARAMETER) and (LastMask and EV_RINGTE <> 0) then begin LastMask := DefEventMask and not EV_RINGTE; SetCommMask(CidEx, LastMask); end; {!!! added code begin} if (Err <> ERROR_INVALID_PARAMETER) and (Err>0) and Assigned(FOnPortIOError) then FOnPortIOError(H.fOwner, Err) {!!! added code end} end; end;
Добавьте аналогичный код в "ProcessOutputEvent".
- В новом обработчике событий проанализируйте ошибку ввода-вывода и закройте / заново откройте порт.