Проблемы с COM-портом
От: Lomion  
Дата: 23.10.06 11:17
Оценка:
Всем доброго времени суток!!!
Вот с такой проблемкой столкнулся...

есть что-то такого типа кода:

отправитель:
char buf [] = "123456";
while (true)
{
   WriteFile (h, buf, 6, ...);
   Sleep (1000);
}


приемник:
while (true)
{
   char buf [4] = {4};
   DWORD read = 0;

   BOOL ret = ReadFile (h1, buf, 3, &read, &o);
   BOOL retW = WaitForSingleObject (o.hEvent, 100);
   if (retW == 258)
      continue;

   BOOL retG = GetOverlappedResult (h1, &o, &read, false);
   if (read == 0)
      continue;

   std::cout << buf << "\n";
}


т.е. читаем данные из COM-порта по 3 байта...
с другого конца данные льется по 6 байт с интервалом 1000 мс...

таймаут чтения 100 мс...
по идее, должно выводиться:

123
456
123
456
...

но выводиться:

123
456
456
456
456
...

Если увеличить интервал чтения до 1500, все работает...
В общем случае, корректно работает, если интервал чтения превышает интервал отправки...

З.Ы. работа идет в асинхронном режиме
Re: Проблемы с COM-портом
От: gordienkos Россия  
Дата: 23.10.06 12:18
Оценка:
Реальные таймауты чтения записи задаются SetCommTimeout. И при некотором везении WaitForSingleObject никогда не вернет WAIT_TIMEOUT, при том, что новых данных в порту нет.

IMHO:
Если чтение в обработчике оконного сообщения, тогда непонятно что за ReadFile в бесконечном цикле.
Если используете же треды -- то overlapped там нафиг не нужен.
sergo
Re[2]: Проблемы с COM-портом
От: Lomion  
Дата: 23.10.06 12:24
Оценка:
Здравствуйте, gordienkos, Вы писали:

G>Реальные таймауты чтения записи задаются SetCommTimeout. И при некотором везении WaitForSingleObject никогда не вернет WAIT_TIMEOUT, при том, что новых данных в порту нет.


G>IMHO:

G>Если чтение в обработчике оконного сообщения, тогда непонятно что за ReadFile в бесконечном цикле.
G>Если используете же треды -- то overlapped там нафиг не нужен.
Ну а если мне необходимо использовать таймауты???

А вообще, из-за чего такая фигня происходит???
Re: Проблемы с COM-портом
От: Alexey Frolov Беларусь  
Дата: 23.10.06 15:09
Оценка:
Здравствуйте, Lomion, Вы писали:

L>приемник:

L>
L>while (true)
L>{
L>   char buf [4] = {4};
L>   DWORD read = 0;

L>   BOOL ret = ReadFile (h1, buf, 3, &read, &o);

L>   if (ret)
L>     std::cout << buf << "\n";

L>   BOOL retW = WaitForSingleObject (o.hEvent, 100);
L>   if (retW == 258)
L>      continue;

L>   BOOL retG = GetOverlappedResult (h1, &o, &read, false);
L>   if (read == 0)
L>      continue;

L>   std::cout << buf << "\n";
L>}
L>


Я на 100% не уверен, но такое ощущение что вы читаете с помощью ReadFile порцию, выкидываете ее и ждете следующую. Попробуйте добавить в код следующее и посмотрите что получится
Re[2]: Проблемы с COM-портом
От: FDSC Россия consp11.github.io блог
Дата: 23.10.06 18:16
Оценка:
Здравствуйте, Alexey Frolov, Вы писали:
AF>Я на 100% не уверен, но такое ощущение что вы читаете с помощью ReadFile порцию, выкидываете ее и ждете следующую. Попробуйте добавить в код следующее и посмотрите что получится

И что от этого должно измениться?
Re: Проблемы с COM-портом
От: FDSC Россия consp11.github.io блог
Дата: 23.10.06 18:25
Оценка:
Здравствуйте, Lomion, Вы писали:

L>Всем доброго времени суток!!!

L>Вот с такой проблемкой столкнулся...

L>есть что-то такого типа кода:


L>отправитель:

L>
L>char buf [] = "123456";
L>while (true)
L>{
L>   WriteFile (h, buf, 6, ...);
L>   Sleep (1000);
L>}
L>


L>приемник:

L>
L>while (true)
L>{
L>   char buf [4] = {4};
L>   DWORD read = 0;

L>   BOOL ret = ReadFile (h1, buf, 3, &read, &o);
L>   BOOL retW = WaitForSingleObject (o.hEvent, 100);
L>   if (retW == 258)
L>      continue;

L>   BOOL retG = GetOverlappedResult (h1, &o, &read, false);
L>   if (read == 0)
L>      continue;

L>   std::cout << buf << "\n";
L>}
L>


Есть подозрение, что тебе надо в делать вложенный цикл

L>
L>while (true)
L>{
L>   char buf [4] = {4};
L>   DWORD read = 0;

L>   BOOL ret = ReadFile (h1, buf, 3, &read, &o);
do
{
  BOOL retW = WaitForSingleObject (o.hEvent, 100);
} while (retW == 258)


L>   BOOL retG = GetOverlappedResult (h1, &o, &read, false);
L>   if (read == 0)
L>      continue;

L>   std::cout << buf << "\n";
L>}
L>
Re[2]: Проблемы с COM-портом
От: FDSC Россия consp11.github.io блог
Дата: 23.10.06 18:28
Оценка:
Есть подозрение, что тебе надо просто убрать таймаут вообще... совершенно не понятно, зачем он нужен
Re[3]: Проблемы с COM-портом
От: Alexey Frolov Беларусь  
Дата: 24.10.06 09:57
Оценка: 2 (1)
Здравствуйте, FDSC, Вы писали:

FDS>Здравствуйте, Alexey Frolov, Вы писали:

AF>>Я на 100% не уверен, но такое ощущение что вы читаете с помощью ReadFile порцию, выкидываете ее и ждете следующую. Попробуйте добавить в код следующее и посмотрите что получится

FDS>И что от этого должно измениться?


А то что ожидать окончание операции чтения нужно только если ReadFile вернула ERROR_IO_PENDING, а если функция вернула OK то результат уже в буфере и последующее ожидание приведет к таймауту, а бесконечный цикл который вы привели в примере может вообще привести к зависанию потока.

Моя версия как такое получается: ReadFile возвращает ok, в буфере уже лежит "123", последующий Wait обрывается на таймауте, так как операция завершена (подозреваю что event с автоматическим сбросом), а заново событие уже не просигнализирует. GetOverlappedResult скажет что 0 байт прочитано, такие выводы я сделал прочитав msdn

The results reported by the GetOverlappedResult function are those of the specified handle's last overlapped operation to which the specified OVERLAPPED structure was provided, and for which the operation's results were pending. A pending operation is indicated when the function that started the operation returns FALSE, and the GetLastError function returns ERROR_IO_PENDING. When an I/O operation is pending, the function that started the operation resets the hEvent member of the OVERLAPPED structure to the nonsignaled state. Then when the pending operation has been completed, the system sets the event object to the signaled state.

Specify a manual-reset event object in the OVERLAPPED structure. If an auto-reset event object is used, the event handle must not be specified in any other wait operation in the interval between starting the overlapped operation and the call to GetOverlappedResult. For example, the event object is sometimes specified in one of the wait functions to wait for the operation's completion. When the wait function returns, the system sets an auto-reset event's state to nonsignaled, and a subsequent call to GetOverlappedResult with the bWait parameter set to TRUE causes the function to be blocked indefinitely.


Таким образом возвращаемся к операции чтения читаем следующую порцию "456" ReadFile возвращает ERROR_IO_PENDING. И дальше все идет как задумано. Вот такая у меня версия. Поправьте меня где я не прав и я с удовольствием учту свои ошибки и усвою эту тему
Re[4]: Проблемы с COM-портом
От: gordienkos Россия  
Дата: 24.10.06 11:28
Оценка: 6 (2)
Здравствуйте, Alexey Frolov.

A common mistake is to reuse an OVERLAPPED structure before the previous asynchronous operation has been completed. You should use a separate structure for each request.


Ни один приведенный выше пример кода не гарантирует завершения предыдущего завершения асинхронного чтения до нового вызова ReadFile.
sergo
Re[3]: Проблемы с COM-портом
От: gordienkos Россия  
Дата: 24.10.06 14:30
Оценка:
Здравствуйте, Lomion, Вы писали:

L>Здравствуйте, gordienkos, Вы писали:


G>>Реальные таймауты чтения записи задаются SetCommTimeout. И при некотором везении WaitForSingleObject никогда не вернет WAIT_TIMEOUT, при том, что новых данных в порту нет.


G>>IMHO:

G>>Если чтение в обработчике оконного сообщения, тогда непонятно что за ReadFile в бесконечном цикле.
G>>Если используете же треды -- то overlapped там нафиг не нужен.
L>Ну а если мне необходимо использовать таймауты???

L>А вообще, из-за чего такая фигня происходит???


Я далеко не гуру, и могу только предполагать.
Асинхронное чтение заканчивается либо когда полностью заполнен выделенный буфер, либо, когда данных нет или недостаточно, то по истечении таймаута, заданного в SetCommTimeout.
В первых двух циклах чтения данные поступают, заполняют трех-байтовый буфер, асинхронное чтение заканчивается до следующего запуска ReadFile.
В третий раз данные не приходят (задержка 1000 в отправителе), WaitForSingleObject возвращает WAIT_TIMEOUT и запускается новая операция чтения, при том что старая вероятно еще не закончена. И дальше начинается цирк...
А при увеличении задержки в WaitForSingleObject, операции чтения разносятся во времени и перестают накладываться друг на дгуга. Это и создает видимость правильной работы.
sergo
Re[5]: Проблемы с COM-портом
От: Alexey Frolov Беларусь  
Дата: 24.10.06 18:04
Оценка:
Здравствуйте, gordienkos, Вы писали:

G>Здравствуйте, Alexey Frolov.

G>

G>A common mistake is to reuse an OVERLAPPED structure before the previous asynchronous operation has been completed. You should use a separate structure for each request.


G>Ни один приведенный выше пример кода не гарантирует завершения предыдущего завершения асинхронного чтения до нового вызова ReadFile.


Действительно. Согласен с вами. Пожалуй моя поправка не исправит ситуацию. Вывод: нужно переписать код в соответствии с документацией, там кстати и примеры есть. Самый простой вариант как тут уже говорили non-OVERLAPPED I/O.
Re[6]: Проблемы с COM-портом
От: Alexey Frolov Беларусь  
Дата: 24.10.06 18:08
Оценка: :)
Здравствуйте, gordienkos

AF>...Самый простой вариант как тут уже говорили non-OVERLAPPED I/O.

Кстати заметил, вы же это и говорили
Re[7]: Проблемы с COM-портом
От: Lomion  
Дата: 25.10.06 08:31
Оценка:
Здравствуйте, Alexey Frolov, Вы писали:

AF>Здравствуйте, gordienkos


AF>>...Самый простой вариант как тут уже говорили non-OVERLAPPED I/O.

AF>Кстати заметил, вы же это и говорили


Э-э-э-э...
Т. е. надо еще обрабатывать ERROR_IO_INCOMPLETE? или я что-то не понял?
А это будет очень нагло, если я попрошу примерчик накидать?
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.