Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "WinAPI";
Текущий архив: 2009.10.11;
Скачать: [xml.tar.bz2];

Вниз

Интересный баг с COM портом.   Найти похожие ветки 

 
POP   (2008-08-20 14:43) [0]

Вычитываю инфу с порта так:


OnceAgain:

ClearCommError(PortN, Error, @ComStat);
BytesInBuffer:= ComStat.cbInQue;       // получаю кол-во байтов лежащих в буфере

Overlapped.hEvent:= CreateEvent(nil, false, false, nil);
ReadFile(PortN, buf1, BytesInBuffer, BytesRead, @Overlapped);   // Вычитываю байты из буфера в массив
if WaitForSingleObject(Overlapped.hEvent,2000) <> WAIT_OBJECT_0 then Goto EndRead;
..
..
Goto OnceAgain;


По ClearCommError получаю кол-во байтов в буфере, там лежит правильное число, то что я жду.

В WaitForSingleObject по таймату в 2 сек. не вылетаю, но после ReadFile, BytesRead = 0, то есть прочитано реально 0 байт.

После перехода "Goto OnceAgain" опять на ClearCommError, в BytesInBuffer лежит уже 0, как-будто они были прочитаны.

Порт вирутальный.

В чем может быть причина такого поведения?


 
Сергей М. ©   (2008-08-20 14:46) [1]


> После перехода "Goto OnceAgain"


Как ты, спрашивается, туда попал, если "по таймату .. не вылетаю" ?


 
POP   (2008-08-20 16:21) [2]


> Как ты, спрашивается, туда попал, если "по таймату .. не
> вылетаю" ?


В этом и вопрос.

WaitForSingleObject(Overlapped.hEvent,2000) останавливается по событию, что ф-я ReadFile завершила свою работу, но после нее в BytesRead лежит 0


 
Сергей М. ©   (2008-08-20 16:29) [3]

ReadFile - функция !

С какого перепугу ты используешь ее как процедуру ?


 
POP   (2008-08-20 16:38) [4]

А ClearCommError не ф-я разве?


 
Сергей М. ©   (2008-08-20 16:43) [5]

Ты не ответил на вопрос ..


 
brother ©   (2008-08-21 05:00) [6]

> Ты не ответил на вопрос ..

зацени ;)
The ReadFile function reads data from a file, starting at the position indicated by the file pointer. After the read operation has been completed, the file pointer is adjusted by the number of bytes actually read, unless the file handle is created with the overlapped attribute. If the file handle is created for overlapped input and output (I/O), the application must adjust the position of the file pointer after the read operation.

BOOL ReadFile(

   HANDLE hFile, // handle of file to read
   LPVOID lpBuffer, // address of buffer that receives data  
   DWORD nNumberOfBytesToRead, // number of bytes to read
   LPDWORD lpNumberOfBytesRead, // address of number of bytes read
   LPOVERLAPPED lpOverlapped  // address of structure for data
  );


 
Вариант   (2008-08-21 07:19) [7]


> POP   (20.08.08 14:43)

Первое, как уже говорили, надо проверить результат возвращаемый ReadFile, кстати и ClearCommError тоже....
Второе, если вызов всех функций сделан верно, все параметры переданы верно, ошибок нет или это ошибка для ReadFile (см. GetLastError) ERROR_IO_PENDING,  то и в этом случае никто не гарантирует, что в BytesRead всегда будет передано верное количество прочитанных байт при  использовании функции ReadFile в overlapped режиме. Для получения точного количества байт полученного в этом случае надо заменить в твоем коде WaitForSingleObject на GetOverlappedResult.
Примеры кода можно найти в MSDN в топике на ReadFile


 
tesseract ©   (2008-08-21 13:01) [8]


> то и в этом случае никто не гарантирует, что в BytesRead
> всегда будет передано верное количество прочитанных байт
> при  использовании функции ReadFile в overlapped режиме.
>  


ReadFile  в ovelapped, вроде как начинает операцию считывания, но вот заканчивать её надо GetOverlappedResult.  Тем более что в данном случае режим отложенного чтения вообще можно не использовать - ведь данные-то то одназначно в буфере есть, зачем лишний дескриптор заводить ?


 
Вариант   (2008-08-21 15:06) [9]


> tesseract ©   (21.08.08 13:01) [8]


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

Данные есть - с этим соглашусь. И даже скорее всего в этом случае (но не буду утверждать однозначно, так как это не факт) ReadFile в overlapped режиме в данном случае вернул бы true (то есть чтение в буфер достаточного размера байт числом ComStat.cbInQue).  Но читать в overlapped режиме все же надо, если порт был открыт в overlapped режиме (правда автор об этом умолчал, но думаю так и есть).


 
POP   (2008-08-21 15:20) [10]

По порядку:

1) GetOverlappedResult не работает под Win95, 98, ME, чтобы работало везде, применяется CreateEvent в паре с WaitForSingleObject, что взаимозаменяемо с GetOverlappedResult.

Приведенный выше код работает везде с любыми мобильниками, с хардварными и вирутальными COM портами. Не работает только с мобилами одной марки (видимо USB дрова левые). Причем другой не родной софт для этих моделей работает.

2) Прочитал где-то, что нужно обязательно использовать 3 разные структуры Overlapped для WriteFile , WaitCommEvent, ReadFile. Видимо это нужно при реализации с потоками, чтобы запросы к Overlapped не пересекались. Сделал на всяких пожарный, хотя у меня все по порядку выполняется, без потоков.

3) Тех моделей на которых не работает у меня нет. На тех где я тестирую (на любых портах) WriteFile, а затем WaitCommEvent завершаются с False и GetLastError выдает Error_IO_Pending, что означает, что ассинхронная операция записи и далее ожидания прилета конечного символа в пакете (SetCommMask(PortN, EV_RXFLAG)) начались. Далее WaitForSingleObject(Overlapped2.hEvent,2000) в течении 2 сек ожидает окончания ассинхронной операции.. все отрабатывается.

Конечный символ в пакете прилетел, получаю кол-во символов в буфере (готовых для чтения ReadFile) через ClearCommError. Прилетает правильное число (которое я ожидаю).

Далее ReadFile (для моделей на которых все работает, то есть почти все) сразу выдает True, GetLastError = 0, BytesRead = тоже самое число, что полученное в ClearCommError.

То есть асинхронная операция не начиналась и все за раз прочиталось, так как нужное кол-вл байт уже лежало в буфере. А значит дальнейшее ожидания события по WaitForSingleObject уже не отрабатывает, и она всегда выдает, что все отлично = WAIT_OBJECT_0

Все не так, для ReadFile, для моделей на которых не работает. В буфере лежит нужное и правильное число прилетевших байт, ReadFile выдает False, GetLastError = ERROR_IO_Pending (ассинхронная операция началась).

WaitForSingleObject(Overlapped3.hEvent,4000) (увеличил до 4 сек ожидание) сразу выдает = WAIT_OBJECT_0

То есть ничего не ожидает. Соответсвенно BytesRead = 0.

Вывод.

Может действительно в USB дровах не реализована работа с WaitForSingleObject?


 
Вариант   (2008-08-21 16:12) [11]


> POP   (21.08.08 15:20) [10]



> 1) GetOverlappedResult не работает под Win95, 98, ME, чтобы
> работало везде, применяется CreateEvent в паре с WaitForSingleObject,
>  что взаимозаменяемо с GetOverlappedResult.



> Далее ReadFile (для моделей на которых все работает, то
> есть почти все) сразу выдает True, GetLastError = 0, BytesRead
> = тоже самое число, что полученное в ClearCommError.
>
> То есть асинхронная операция не начиналась и все за раз
> прочиталось, так как нужное кол-вл байт уже лежало в буфере.
>  А значит дальнейшее ожидания события по WaitForSingleObject
> уже не отрабатывает, и она всегда выдает, что все отлично
> = WAIT_OBJECT_0


В идеале так и должно быть.

Про GetOverlappedResult - возвращает число переданных операцией байт (в данном случае прочитанных)
Совет для нерабочего случая (не правильно это, но что-то посоветовать еще трудно без подробного кода и отладки) - забудь про BytesRead в случае для ReadFile в overlapped режиме,по крайней мере если ReadFile вернул false.
Так как байты уже в буфере, то считай, что прочитал все что в cbInQue после
WaitForSingleObject(Overlapped3.hEvent,4000) если результат  = WAIT_OBJECT_0

Другого посоветовать не могу в твоей ситуации. И сказать что-то о кривых дровах тоже.   Попробуй....проверь что будет в буфере.

Вариант второй и более верный на мой взгляд для твоего спорного случая   -
Работать не в overlapped режиме, порт открывать без флага FILE_FLAG_OVERLAPPED, тогда и для чтения и записи не надо делать overlapped вызовов. Тогда в случае успешного чтения BytesRead будет содержать верное число байт.


 
POP   (2008-08-21 17:21) [12]


> забудь про BytesRead в случае для ReadFile в overlapped
> режиме,по крайней мере если ReadFile вернул false.


Хмм.. надо попробовать. Отпишу как проверю, заодно поставлю GetOvelappedResult, после WaitForForSibgleObject = WAIT_OBJECT_0, чтобы посмотреть какой количество байт она выдаст.

Сразу вопрос, если ReadFile возвращает False, то впоследствие (когда сработает WaitForForSibgleObject = WAIT_OBJECT_0) Винда должна заполнить переменную BytesRead правильным кол-вом байт.

Должна ли BytesRead быть глобальной переменной в этом случае? Она у меня локальная в данный момент.


 
Сергей М. ©   (2008-08-21 17:46) [13]


> если ReadFile возвращает False, то


.. то если ты в полном трезвоздравомыслии задействовал overlapped mode, ты первым делом обязан проверить, а не равен ли GetLastError значению ERROR_IO_PENDING !

А ты даже не почесался это сделать)


 
POP   (2008-08-21 18:12) [14]


> то если ты в полном трезвоздравомыслии задействовал overlapped
> mode, ты первым делом обязан проверить, а не равен ли GetLastError
> значению ERROR_IO_PENDING !А ты даже не почесался это сделать)


А зачем?

Ведь ReadFile для большинства случаев сразу возвращает True, так как я запрашиваю заранее известное кол-во байтов уже лежащих в буфере, готовых для чтения.

Да и для случая False, нет смысла проверять на ERROR_IO_PENDING в ReadFile, так-как такая проверка на завершенность чтения проводиться в WaitForSingleObject.


 
Сергей М. ©   (2008-08-21 18:47) [15]


> А зачем?


Что "зачем" ? чесаться  "зачем" ? Или что ?

И какое еще нахрен "большинство случаев", если тебе черным по белому сказано насчет GetLastError ?


 
POP   (2008-08-21 19:20) [16]


>  какое еще нахрен "большинство случаев", если тебе черным
> по белому сказано насчет GetLastError ?


Я уже написал, что ReadFile либо по True выходит, в этом случае GetLastError = 0, либо по False, в этом случае в GetLastError лежит ERROR_IO_PENDING, после этого в обоих случаях WaitForSingleObject выдает о завершенности ассинхронной ситуации. Ео для второго случая в BytesRead лежит 0.

Еще вопросы?


 
Вариант   (2008-08-22 06:13) [17]


> POP   (21.08.08 19:20) [16]




> либо по False, в этом случае в GetLastError лежит ERROR_IO_PENDING


А если во время или даже перед чтением в другом потоке закрыть Handle порта?
Ошибка будет, но другая. Так что проверить на ERROR_IO_PENDING надо, ошибки всякие бывают.  


> заодно поставлю GetOvelappedResult, после WaitForForSibgleObject
> = WAIT_OBJECT_0,


Напиши - интересно, потому что ту ситуацию, которую ты описываешь в


> POP   (21.08.08 15:20) [10]

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


 
Вариант   (2008-08-22 08:41) [18]


> POP   (21.08.08 17:21) [12]



> заодно поставлю GetOvelappedResult, после WaitForForSibgleObject
> = WAIT_OBJECT_0, чтобы посмотреть какой количество байт
> она выдаст.


Кстати, забыл сказать, если Event не ManualReset как у тебя


> Overlapped.hEvent:= CreateEvent(nil, false, false, nil);


то с GetOvelappedResult после WaitForForSibgleObject возможно могут возникнуть проблемы.


 
POP   (2008-08-22 15:16) [19]


> Вариант


Спасибо за совет игнорировать то, что выдает ReadFile.

Все работает.

Если ReadFile выдает Fail и GetLastError = ERROR_IO_Pending, то после ожидания окончания ассинхронной операции по WaitForSingleObject = WAIT_OBJECT_0 в переменной BytesRead ничего не лежит, она не заполняется виндой, заполняется только если ReadFile выдает True.

Если после удачного ожидания по WaitForSingleObject вызвать GetOvelappedResult, то она выдаст правильное число байт, которое лежало в буфере по ClearCommError.

Но я GetOvelappedResult не юзаю из-за неуниверсальности, поэтому просто использую то число, которое выдало ClearCommError (при условии, что WaitForSingleObject отработал нормально)

Так, что все пашет и вертиться сейчас.


 
Сергей М. ©   (2008-08-22 15:22) [20]


> я GetOvelappedResult не юзаю из-за неуниверсальности


Какой еще нафих "универсальности" ?

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


 
POP   (2008-08-22 15:24) [21]

То есть можно подитожить:

Если в буфере лежит некое число байт и это количество запросить в ReadFile, то не всегда за раз все читается... бывает, что винда в ассинхрон переводит.


 
POP   (2008-08-22 15:27) [22]


> Какой еще нафих "универсальности" ?


Ты из-за своей нервозности, через строку читаешь и пропустил то, что я говорил.

А говорил я о работе этих ф-й под разными Windows... иммено в этом смысле универсальность.

GetOverlappedResult не работает под Win95, 98, ME... то, что они устарели, это другой вопрос.

У меня полно юзверей, которые ни в какую с этих Win не слезают годами.


 
Вариант   (2008-08-22 15:55) [23]


> POP   (22.08.08 15:27) [22]

Я не проверял в 95 или 98 винде GetOverlappedResult, но MSDN пишет, что данная функция работает начиная с Windows 95  для коммуникационных устройств. Если ты не проверял это под 98 виндой - попробуй проверь. У меня просто нет возможности этого сделать.... Кстати, можно таки просто перейти на не overlapped модель работы с портом, но это уж на твое усмотрение.


 
Сергей М. ©   (2008-08-22 21:45) [24]

<I
> Ты из-за своей нервозности


Я волнуюсь)
Волнуюсь что ты туп.
А туп ты потому что "вычитываешь инфу" в непонятно какой ОС)
Т.е. ты туп потому, что тебе предложено при формировании топик-старта обозначить ОС, и ты это либо не видишь либо игнорируешь по тупости)

И я еще волнуюсь за то, что ты и подобные тебе тупицы не моргнув глазом постят тупые вопросы куда угодно, но только не разработчику)


 
POP   (2008-08-22 21:56) [25]

Удалено модератором


 
Сергей М. ©   (2008-08-22 22:39) [26]


> POP   (22.08.08 21:56) [25]


Ну ты хам)



Страницы: 1 вся ветка

Форум: "WinAPI";
Текущий архив: 2009.10.11;
Скачать: [xml.tar.bz2];

Наверх





Память: 0.53 MB
Время: 0.006 c
15-1249068357
картман
2009-07-31 23:25
2009.10.11
Не вызывается функция dll из clr-ХП


2-1249889040
DevilDevil
2009-08-10 11:24
2009.10.11
FindFirst, FindNext... Как быстрее?


4-1219358604
demon
2008-08-22 02:43
2009.10.11
Почему не отлавливаються двойные клики?


15-1249761808
Andy BitOff
2009-08-09 00:03
2009.10.11
Palladin, с Днем рождения!


6-1207843756
anton
2008-04-10 20:09
2009.10.11
поменять стиль документа





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский