На главную Наши проекты:
Журнал   ·   Discuz!ML   ·   Wiki   ·   DRKB   ·   Помощь проекту
ПРАВИЛА FAQ Помощь Участники Календарь Избранное RSS
msm.ru
! Правила раздела Visual C++ / MFC / WTL (далее Раздела)
1) На Раздел распространяются все Правила Форума.
2) Перед тем, как создать новый топик, убедитесь, что Вы читали Правила создания тем в Разделе.
3) Вопросы, не связанные с программированием (настройки MS Visual Studio, книги, библиотеки и т.д.),
обсуждаются в разделе C/C++: Прочее
4) Вопросы разработки .NET (Windows Form, C++/CLI и т.п.) приложений на Visual C++/C# обсуждаются в разделе .NET.
5) Нарушение Правил может повлечь наказание со стороны модераторов.

Полезные ссылки:
user posted image FAQ Раздела user posted image Обновления для FAQ Раздела user posted image Поиск по Разделу user posted image MSDN Library Online
Модераторы: ElcnU
Страницы: (2) 1 [2]  все  ( Перейти к последнему сообщению )  
> Оптимизация асинхронного I/O в COM порт , многопоточность
    И снова приветствую всех!
    Есть большая просьба - у кого есть модем внутренний или внешний или подобное оборудование - проверьте пожалуйста, будет ли у вас работать этот код. У меня PCI модем на COM3 у товарища - обычный модем на СОМ2. У меня все прекрасно работает - у него - нет. Понять причину немогу.
    Если кто подскажет в чем дело - буду очень признателен.
    ExpandedWrap disabled
      #include <windows.h>
      #include <conio.h>
      #include <iostream.h>
      #define MAX 1024
       
      DWORD WINAPI ThreadFunc(LPVOID lpParam );
      void Error(void);
      bool Terminate=TRUE;
      HANDLE hPort = NULL;
      char *temp;
       
      void main(void)
      {
      //Запрашивам имя порта
      clrscr();
      temp=(char*)calloc(MAX,sizeof(char));
      strcpy(temp,"\n\nВведите номер открываемого порта, например COM1 или COM3\n\n");
      CharToOem((const char*)temp,(char*)temp);
      cout<<temp;
      memset(temp, '\0',MAX);
      cin>>temp;
       
      //открываем порт
      hPort=CreateFile(temp,
                       GENERIC_WRITE|GENERIC_READ,
                       0,
                       NULL,
                       OPEN_EXISTING,
                       FILE_FLAG_OVERLAPPED,
                       NULL);
      if(hPort!=INVALID_HANDLE_VALUE){
         cout<<"\nOpenPort - ok\n";}
         else{
             Error();getch();exit(1);
             }
      //проводим настройку порта
      DCB          *dcb;
      COMMTIMEOUTS  ct;
       
      //скорости, четности, битность битов, стоп биты...
      dcb=(DCB*)HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(DCB));
      dcb->DCBlength=sizeof(DCB);
      BuildCommDCB("baud=9600 parity=N data=8 stop=1",dcb);
      dcb->fNull=TRUE;
       
      //таймауты порта
      ct.ReadIntervalTimeout=10;
      ct.ReadTotalTimeoutMultiplier=ct.ReadTotalTimeoutConstant=0;
      ct.WriteTotalTimeoutMultiplier=ct.WriteTotalTimeoutConstant=0;
       
      SetCommState(hPort,dcb);
      SetCommTimeouts(hPort,&ct);
       
      //очистка порта перед работой очищаем все что можно
      PurgeComm(hPort,PURGE_TXABORT|PURGE_RXABORT|PURGE_TXCLEAR|PURGE_RXCLEAR);
      SetupComm(hPort,256,256); //последние два параметра - длина вх.\ вых. буфера
      SetCommMask(hPort,EV_RXCHAR); //маска ожидания символа во входном буфере
       
      //Запускаем поток на чтение порта
       
      DWORD lpThreadId;
      HANDLE hThread = CreateThread(
          (LPSECURITY_ATTRIBUTES) NULL,   // pointer to thread security attributes
          (DWORD) 0,                          // initial thread stack size, in bytes
          (LPTHREAD_START_ROUTINE) &ThreadFunc,  // pointer to thread function
          (LPVOID) &hPort,                         // argument for new thread
          (DWORD) 0,                          // creation flags
          (LPDWORD) &lpThreadId               // pointer to returned thread identifier
         );
       
      //Работаем с пользователем
      for(;Terminate==TRUE;)
      {
      strcpy(temp,"\n\nВведите команду, например ATI1-ATI7 или ATZ\nВыход - восклицательный знак '!'\n");
      CharToOem((const char*)temp,(char*)temp);
      cout<<temp;
      memset(temp, '\0',MAX);
      cin>>temp;
       
      if(strcmp(temp,"!")==0)
        {
        TerminateThread(hThread,1);
        clrscr();
        cout<<"\nBye!\n";
        exit(0);
        }
       
      DWORD dwWrite ;
      OVERLAPPED OverWrite;
      strcat(temp,"\r\n");
       
      OverWrite.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
      if (OverWrite.hEvent == NULL)
         {
         cout<<"\n\nError creating write event\n\n"; Error(); exit(1);
         }
      if (!WriteFile(hPort, temp, sizeof(temp),&dwWrite, &OverWrite))
          {
          if(GetLastError() != ERROR_IO_PENDING)
             {
             cout<<"\n\nError writing port\n\n"; Error(); exit(1);
             }
           }
      else
          {
          cout<<"\n\nWrited to port\n"<<temp;
          }
      //getch();    
      }
       
      getch();
      }
       
       
      DWORD WINAPI ThreadFunc(LPVOID lpParam )
      {
      Terminate=TRUE;
      HANDLE hPort=*(HANDLE*)lpParam;
      COMSTAT ComStat;
      DWORD dwMask, dwError, dwRead;
      OVERLAPPED OverRead;
      char Buf[100]="";
       
      OverRead.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
      if (OverRead.hEvent == NULL)
         {
         cout<<"\n\nError creating read event\n\n"; Error(); exit(1);
         }
      while (Terminate)
          {
          if (!WaitCommEvent(hPort, &dwMask,(LPOVERLAPPED)&OverRead))
            {
            if (GetLastError() == ERROR_IO_PENDING){
                WaitForSingleObject(OverRead.hEvent, INFINITE);
                }
            else{
                cout<<"\n\nError waiting port event\n\n"; Error(); exit(1);
                }
             }
          if (!ClearCommError(hPort, &dwError, &ComStat))
             {
             cout<<"\n\nError clearing port\n\n"; Error(); exit(1);
             }
       
          dwRead = ComStat.cbInQue;
          if(dwRead > 0)
            {
           if (!ReadFile(hPort, Buf, dwRead, &dwRead, &OverRead))
              {
              cout<<"\n\nError reading port\n\n"; Error(); exit(1);
              }
             // В Buf находятся прочитанные байты
             // идет обработка принятых байтов ...
             cout<<"\n\n*****************************\n"<<
             "DATA_FROM_PORT:\n"<<(char*)Buf<<
                   "\n*****************************\n";
             memset(Buf, '\0', strlen(Buf) - 1);
           }
          }
      return 0;
      }
       
      void Error(void)
      {
      LPVOID lpMsgBuf;
      FormatMessage(
          FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
          NULL,
          GetLastError(),
          MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
          (LPTSTR) &lpMsgBuf,
          0,
          NULL);
      CharToOem((const char*)lpMsgBuf,(char*)lpMsgBuf);
      cout<<"\n\nGetLastError:\n\n"<<(const char*)lpMsgBuf<<"\n\n";
      LocalFree( lpMsgBuf );
      }
      надо выкладывать не код, а солюшен, что бы не трахаться с созданием нового проекта, удалением оттуда файлов, вставкой новых.

      т.к. порт открыт как оверлапед, то
      Цитата

      ExpandedWrap disabled
        if (!ReadFile(hPort, Buf, dwRead, &dwRead, &OverRead))
                {
                cout<<"\n\nError reading port\n\n"; Error(); exit(1);
                }


      если не считалось то нормально и нужно ждать события OverRead.hEvent ( когда считается), а не выходить с ошибкой.

      в чем проблема, почему не работает на другом компе?
      Сообщение отредактировано: sploid -
        ExpandedWrap disabled
          if (!WriteFile(hPort, temp, sizeof(temp),&dwWrite, &OverWrite))

        Размер указателя? Ты уверен что так правильно? ;)
        ExpandedWrap disabled
          OverRead.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
          ...
          WaitForSingleObject(OverRead.hEvent, INFINITE);

        У тебя эвент с мануальным сбросом, но, что-то не где не видно чтоб ты его сбрасывал...
        ExpandedWrap disabled
          char Buf[100]="";
          ...
          dwRead = ComStat.cbInQue;
          ...
          if (!ReadFile(hPort, Buf, dwRead, &dwRead, &OverRead))

        А не ты разве простраивал буффер в 256? Шанс схлопотать исключение не велик, но если схлопочешь - мало не покажется...
        ExpandedWrap disabled
          BuildCommDCB("baud=9600 parity=N data=8 stop=1",dcb);

        А остальные настройки у ваших компов одинаковые?
          Цитата sploid @
          надо выкладывать не код, а солюшен, что бы не трахаться с созданием нового проекта, удалением оттуда файлов, вставкой новых.

          Как я уже писал у меня компилятор - BCB 6.0 какие в нем солюшены - я не знаю. И так весь VCL убрал дабы совместимость была, и консоль - по тойже причине.
          Цитата sploid @

          т.к. порт открыт как оверлапед, то
          Цитата
          if (!ReadFile(hPort, Buf, dwRead, &dwRead, &OverRead))
          {
          cout<<"\n\nError reading port\n\n"; Error(); exit(1);
          }
          если не считалось то нормально и нужно ждать события OverRead.hEvent ( когда считается), а не выходить с ошибкой.

          Кстати, валится именно на этом... Может я не так как-то делаю... Сделал так:
          ExpandedWrap disabled
            if (!ReadFile(hPort, Buf, dwRead, &dwRead, &OverRead))
                    {
                    WaitForSingleObject(OverRead.hEvent, INFINITE);
                           ....
                    }

          Теперь вечно висит на WaitForSingleObject ... мда короче. Разбираться еще и разбираться...
          Цитата sploid @

          в чем проблема, почему не работает на другом компе?

          Работаем удаленно - другой комп в другом городе. Сказать 100% точно - не могу. Но 99,9% проблема в том что вышеописанная конструкция - корявая, как впрочем видимо и все остальное. :(


          Цитата Ace @
          if (!WriteFile(hPort, temp, sizeof(temp),&dwWrite, &OverWrite))

          Размер указателя? Ты уверен что так правильно?

          Косяк, спасибо, учтем.

          Цитата Ace @

          OverRead.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
          ...
          WaitForSingleObject(OverRead.hEvent, INFINITE);

          У тебя эвент с мануальным сбросом, но, что-то не где не видно чтоб ты его сбрасывал...

          Да честно говоря - х.з. смотрел в МСДНе исходники их. Вроде тоже нигде не сбрасывают. А может и сбрасывают, там такое наворочено, что черт ногу сломит. :wall: Буду еще смотреть.

          Цитата Ace @

          char Buf[100]="";
          ...
          dwRead = ComStat.cbInQue;
          ...
          if (!ReadFile(hPort, Buf, dwRead, &dwRead, &OverRead))

          А не ты разве простраивал буффер в 256? Шанс схлопотать исключение не велик, но если схлопочешь - мало не покажется...

          Самое малое из моих зол... ;) :D :lool:
          Цитата Ace @

          BuildCommDCB("baud=9600 parity=N data=8 stop=1",dcb);
          А остальные настройки у ваших компов одинаковые?


          Да вроде бы да. При таких же параметрах HyperTerminal пашет ...

          В общем тему пока закрывать не буду. Попробую еще с исходниками с МСДНа разобраться. Если поставить эти параметры туда, их прога - катит. На этом можно было бы и остановиться, но меня бесят две вещи - уровень собственного понимания этой проблемы (над этим надо работать...) и весь тот зоопарк с ресурсами, критическими секциями, десятью отдельными *.с файлами в проекте и прочей мишурой из МСДН сурсов... >:( Короче работы по горло.
          Всем большое спасибо что откликнулись - буду искать дальше. :)
          1 пользователей читают эту тему (1 гостей и 0 скрытых пользователей)
          0 пользователей:


          Рейтинг@Mail.ru
          [ Script execution time: 0,1368 ]   [ 15 queries used ]   [ Generated: 20.11.25, 07:08 GMT ]