Восстановление из выпадающего списка ComPort

D5-pro: использование TurboPower APro и компонентов ComPort и терминала с USB Arduino Nano для очень простого Comms-терминала. Все работает нормально, пока я не отключу USB для симуляции потери порта. Все просто зависает и не будет перезагружаться без закрытия и перезапуска.

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

Я также попробовал TComPort и Terminal от Dejan Crnila, и он также не останавливается. Это на самом деле происходит сбой, и я должен использовать TaskManager, чтобы закрыть все это.

Может кто-нибудь, пожалуйста, сообщите мне некоторые фрагменты кода, которые могут указывать на отсутствие порта. Или есть лучший бесплатный компонент для этого.

1 ответ

Требуются некоторые модификации в модуле AwUser.

  1. Добавьте новое событие для ошибок ввода / вывода.

    TPortIOErrorEvent = процедура (CP: TObject; Ошибка: кардинальная) объекта; свойство OnPortIOError: TPortIOErrorEvent read FOnPortIOError write FOnPortIOError;

  2. Измените метод 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;
    
  3. Добавьте аналогичный код в "ProcessOutputEvent".

  4. В новом обработчике событий проанализируйте ошибку ввода-вывода и закройте / заново откройте порт.
Другие вопросы по тегам