Наши проекты:
Журнал · Discuz!ML · Wiki · DRKB · Помощь проекту |
||
ПРАВИЛА | FAQ | Помощь | Поиск | Участники | Календарь | Избранное | RSS |
[3.16.15.149] |
|
Сообщ.
#1
,
|
|
|
Доброго всем дня!
Написал прогу которая слушает COM-порт, количество принимаемых данных не известно, т.е что есть то и передал в основную программу. Проблема такая, не могу завершить поток, блокируется в функции WaitCommEvent по событию SetCommMask(hPort, EV_RXCHAR). Тут уже писали варианты CloseHandle(), SetCommBreak() и т.д. ни чего не работает, OVERLAPPED не поможет, пишу по WinCE, асинхронного ввода-вывода там нет. Попробовал просто сканировать на прием через таймаут, но что не очень нравиться. //установить таймауты 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); //закрыть порт |
Сообщ.
#2
,
|
|
|
сделай так
SetCommMask(hPort, EV_BREAK); SetCommBreak(hPort); или еще попробовать SetCommMask(hPort, 0); |
Сообщ.
#3
,
|
|
|
SetCommMask(hPort, EV_BREAK); SetCommBreak(hPort); или SetCommMask(hPort, 0); Не помогает |
Сообщ.
#4
,
|
|
|
а как ты используешь WaitCommEvent ?
|
Сообщ.
#5
,
|
|
|
Делал так:
// После открытия, очистка порта: 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; } |
Сообщ.
#6
,
|
|
|
1) Укажи, что ты хочешь отслеживать сообщение BREAK
SetCommMask (hPort, EV_RXCHAR | EV_TXEMPTY | EV_BREAK); 2) Проверяй на BREAK if((mask & EV_RXCHAR)!= 0) { ... } else if ((mask & EV_BREAK)!= 0) { break; } 3) В конце работы шли BREAK и жди окончания работы потока 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; } |
Сообщ.
#7
,
|
|
|
что я совсем ни чего не понимаю, реализовал как ты предлагаешь:
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, может такие грабли из за семерки. Уже на знаю на что грешить. |
Сообщ.
#8
,
|
|
|
Хммм... нашел в чем проблема, она даже описана в MSDN'е
тут есть решение. |
Сообщ.
#9
,
|
|
|
Посмотрел..., намекают использовать OVERLAPPED как выход из ожидания, не подойдет, пишу для WinCE.
менять маску SetCommMask(...) без OVERLAPPED из другого потока..., функция блокируется, использовать CancelIo тоже не катит. Смотрел CSerial, ни чего нового не нашел. Решения не вижу. |
Сообщ.
#10
,
|
|
|
ну там же было написано, что если просто закрыть ком-порт, то WaitCommEvent отвалится с ошибкой.
|
Сообщ.
#11
,
|
|
|
CloseHandle(hPort)... пробовал та же песня, уходит в ожидание.
|