На главную Наши проекты:
Журнал   ·   Discuz!ML   ·   Wiki   ·   DRKB   ·   Помощь проекту
ПРАВИЛА FAQ Помощь Участники Календарь Избранное RSS
msm.ru
Модераторы: ElcnU
  
> Работа с COM-порт выход их потока в Win CE , WaitCommEvent блокирует поток
    Доброго всем дня!

    Написал прогу которая слушает COM-порт, количество принимаемых данных не известно, т.е что есть то и передал в основную программу.
    Проблема такая, не могу завершить поток, блокируется в функции WaitCommEvent по событию SetCommMask(hPort, EV_RXCHAR). Тут уже писали варианты CloseHandle(), SetCommBreak() и т.д. ни чего не работает, OVERLAPPED не поможет, пишу по WinCE, асинхронного ввода-вывода там нет.

    Попробовал просто сканировать на прием через таймаут, но что не очень нравиться.

    ExpandedWrap disabled
      //установить таймауты
      m_Timeouts.ReadIntervalTimeout = 0;       //таймаут между двумя символами
      m_Timeouts.ReadTotalTimeoutMultiplier = 10;   //общий таймаут операции чтения
      m_Timeouts.ReadTotalTimeoutConstant = 0;      //константа для общего таймаута операции чтения
      m_Timeouts.WriteTotalTimeoutMultiplier = 500; //общий таймаут операции записи
      m_Timeouts.WriteTotalTimeoutConstant = 0;     //константа для общего таймаута операции записи
       
       
      //записать структуру таймаутов в порт
      if(!SetCommTimeouts(hPort, &m_Timeouts ))
      {
         m_TextErr = L"Неудалось записать timeouts";
         CloseHandle(hPort);     //закрыть порт
         hPort= NULL;            //обнулить переменную для дескриптора порта
         return false;
      }
       
      // поток
      ....
      do
      {
        // Read the data from the serial port.
        if (!ReadFile(hPort, &m_Buffer[m_RxCounter], 1, &rxCounter, NULL))
        {
          m_Status |= COM_PORT_READ_ERROR;
          break;
        }
        
        m_RxCounter += rxCounter;
       
      }while (rxCounter == 1);
       
      // выход
      CloseHandle(hPort);     //закрыть порт
      сделай так
      ExpandedWrap disabled
        SetCommMask(hPort, EV_BREAK);
        SetCommBreak(hPort);


      или еще попробовать
      ExpandedWrap disabled
        SetCommMask(hPort, 0);
        ExpandedWrap disabled
          SetCommMask(hPort, EV_BREAK);
          SetCommBreak(hPort);
          или
          SetCommMask(hPort, 0);

        Не помогает :wall:
          а как ты используешь WaitCommEvent ?
            Делал так:
            ExpandedWrap disabled
              // После открытия, очистка порта:
              PurgeComm(hPort, PURGE_TXABORT|PURGE_RXABORT|PURGE_TXCLEAR|PURGE_RXCLEAR);
               
              //установить маску событий
              SetCommMask(hPort, EV_RXCHAR | EV_TXEMPTY);
               
              // поток - чтение данных с сом-порта
              void TComPortRx::ThreadRun(void)
              {
                DWORD mask, rxCounter = 0;    // счетчик принятых байт
               
                while(hPort != NULL)
                {
                  //приостановить поток до прихода байта
                  WaitCommEvent(hPort, &mask, NULL);
               
                  //если произошло именно событие прихода байта
                  if((mask & EV_RXCHAR)!= 0)
                  {
                    if (!ReadFile(hPort, m_Buffer, 1, &rxCounter, NULL))
                    {
                      m_Status |= COM_PORT_READ_ERROR;
                    }
                    else
                    {
                      // обработка
                    }
                  }
                }
              }
               
              // закрыть порт, возвращает true - порт успешно закрыт
              bool TComPortRx::Close()
              {
                if (hPort != NULL)
                {
                  // пытаемся выйти из WaitCommEvent
                  SetCommMask(hPort, 0);
               
                  // ждем завершение потока
                  if(WaitForSingleObject(m_hRunThread, 20)!=WAIT_OBJECT_0)
                    TerminateThread(m_hRunThread, 0);
               
                  // закрыть порт
                  CloseHandle(hPort);
                  // дескриптор потока
                  CloseHandle(m_hRunThread);
               
                  hPort = NULL;
                  m_hRunThread = NULL;
              }
              1) Укажи, что ты хочешь отслеживать сообщение BREAK
              ExpandedWrap disabled
                SetCommMask (hPort, EV_RXCHAR | EV_TXEMPTY | EV_BREAK);


              2) Проверяй на BREAK
              ExpandedWrap disabled
                    if((mask & EV_RXCHAR)!= 0)
                    {
                       ...
                    }
                    else if ((mask & EV_BREAK)!= 0)
                    {
                       break;
                    }


              3) В конце работы шли BREAK и жди окончания работы потока
              ExpandedWrap disabled
                bool TComPortRx::Close()
                {
                  if (hPort != NULL)
                  {
                    SetCommBreak (hPort);
                 
                    // ждем завершение потока
                    if(WaitForSingleObject(m_hRunThread, 20)!=WAIT_OBJECT_0) // 20 милисекунд мало, подожди хотя бы 2 секунды. но тут уж дело хозяйское :)
                      TerminateThread(m_hRunThread, 0);
                 
                    // закрыть порт
                    CloseHandle(hPort);
                    // дескриптор потока
                    CloseHandle(m_hRunThread);
                 
                    hPort = NULL;
                    m_hRunThread = NULL;
                }
                что я совсем ни чего не понимаю, реализовал как ты предлагаешь:

                ExpandedWrap disabled
                  hPort= CreateFile( (LPCTSTR)name, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL );
                   
                  SetCommMask (hPort, EV_RXCHAR | EV_TXEMPTY | EV_BREAK);
                   
                  WaitCommEvent(hPort, &mask, NULL);
                  if((mask & EV_RXCHAR)!= 0)
                  {
                         ...
                  }
                  else if ((mask & EV_BREAK)!= 0)
                  {
                      break;
                  }
                   
                  bool TComPortRx::Close()
                  {
                    if (hPort != NULL)
                    {
                      SetCommBreak (hPort);
                   
                      // ждем завершение потока
                      if(WaitForSingleObject(m_hRunThread, 20)!=WAIT_OBJECT_0)
                        TerminateThread(m_hRunThread, 0);
                   
                      // закрыть порт
                      CloseHandle(hPort);
                      // дескриптор потока
                      CloseHandle(m_hRunThread);
                   
                      hPort = NULL;
                      m_hRunThread = NULL;
                  }


                так он на SetCommBreak(hPort) уходит в глубокую спячку. Я ща пытаюсь отладится на компе в VS2008, операционка Windows 7, может такие грабли из за семерки. Уже на знаю на что грешить. :-?
                  Хммм... нашел в чем проблема, она даже описана в MSDN'е :)
                  тут есть решение.
                    Посмотрел..., намекают использовать OVERLAPPED как выход из ожидания, не подойдет, пишу для WinCE.
                    менять маску SetCommMask(...) без OVERLAPPED из другого потока..., функция блокируется, использовать CancelIo тоже не катит.
                    Смотрел CSerial, ни чего нового не нашел.

                    Решения не вижу. :wall:
                      ну там же было написано, что если просто закрыть ком-порт, то WaitCommEvent отвалится с ошибкой.
                        CloseHandle(hPort)... пробовал та же песня, уходит в ожидание.
                        0 пользователей читают эту тему (0 гостей и 0 скрытых пользователей)
                        0 пользователей:


                        Рейтинг@Mail.ru
                        [ Script execution time: 0,0338 ]   [ 16 queries used ]   [ Generated: 26.04.24, 14:50 GMT ]