Оптимизация асинхронного I/O в COM порт
, многопоточность
![]() |
Наши проекты:
Журнал · Discuz!ML · Wiki · DRKB · Помощь проекту |
|
| ПРАВИЛА | FAQ | Помощь | Поиск | Участники | Календарь | Избранное | RSS |
| [216.73.216.219] |
|
|
Правила раздела Visual C++ / MFC / WTL (далее Раздела)
FAQ Раздела
Обновления для FAQ Раздела
Поиск по Разделу
MSDN Library Online| Страницы: (2) 1 [2] все ( Перейти к последнему сообщению ) |
Оптимизация асинхронного I/O в COM порт
, многопоточность
|
Сообщ.
#16
,
|
|
|
|
И снова приветствую всех!
Есть большая просьба - у кого есть модем внутренний или внешний или подобное оборудование - проверьте пожалуйста, будет ли у вас работать этот код. У меня PCI модем на COM3 у товарища - обычный модем на СОМ2. У меня все прекрасно работает - у него - нет. Понять причину немогу. Если кто подскажет в чем дело - буду очень признателен. ![]() ![]() #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 ); } |
|
Сообщ.
#17
,
|
|
|
|
надо выкладывать не код, а солюшен, что бы не трахаться с созданием нового проекта, удалением оттуда файлов, вставкой новых.
т.к. порт открыт как оверлапед, то Цитата ![]() ![]() if (!ReadFile(hPort, Buf, dwRead, &dwRead, &OverRead)) { cout<<"\n\nError reading port\n\n"; Error(); exit(1); } если не считалось то нормально и нужно ждать события OverRead.hEvent ( когда считается), а не выходить с ошибкой. в чем проблема, почему не работает на другом компе? |
|
Сообщ.
#18
,
|
|
|
|
![]() ![]() if (!WriteFile(hPort, temp, sizeof(temp),&dwWrite, &OverWrite)) Размер указателя? Ты уверен что так правильно? ![]() ![]() OverRead.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL); ... WaitForSingleObject(OverRead.hEvent, INFINITE); У тебя эвент с мануальным сбросом, но, что-то не где не видно чтоб ты его сбрасывал... ![]() ![]() char Buf[100]=""; ... dwRead = ComStat.cbInQue; ... if (!ReadFile(hPort, Buf, dwRead, &dwRead, &OverRead)) А не ты разве простраивал буффер в 256? Шанс схлопотать исключение не велик, но если схлопочешь - мало не покажется... ![]() ![]() BuildCommDCB("baud=9600 parity=N data=8 stop=1",dcb); А остальные настройки у ваших компов одинаковые? |
|
Сообщ.
#19
,
|
|
|
|
Цитата 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 ( когда считается), а не выходить с ошибкой. Кстати, валится именно на этом... Может я не так как-то делаю... Сделал так: ![]() ![]() 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); У тебя эвент с мануальным сбросом, но, что-то не где не видно чтоб ты его сбрасывал... Да честно говоря - х.з. смотрел в МСДНе исходники их. Вроде тоже нигде не сбрасывают. А может и сбрасывают, там такое наворочено, что черт ногу сломит. Буду еще смотреть.Цитата Ace @ char Buf[100]=""; ... dwRead = ComStat.cbInQue; ... if (!ReadFile(hPort, Buf, dwRead, &dwRead, &OverRead)) А не ты разве простраивал буффер в 256? Шанс схлопотать исключение не велик, но если схлопочешь - мало не покажется... Самое малое из моих зол... Цитата Ace @ BuildCommDCB("baud=9600 parity=N data=8 stop=1",dcb); А остальные настройки у ваших компов одинаковые? Да вроде бы да. При таких же параметрах HyperTerminal пашет ... В общем тему пока закрывать не буду. Попробую еще с исходниками с МСДНа разобраться. Если поставить эти параметры туда, их прога - катит. На этом можно было бы и остановиться, но меня бесят две вещи - уровень собственного понимания этой проблемы (над этим надо работать...) и весь тот зоопарк с ресурсами, критическими секциями, десятью отдельными *.с файлами в проекте и прочей мишурой из МСДН сурсов... Короче работы по горло. Всем большое спасибо что откликнулись - буду искать дальше. |