![]() |
| ||
|
|
Новости |
Поиск |
FAQ |
Статьи |
Книги |
Новости VCL
| | Форумы ЧАТ |
Орешник |
|
| |||
| |||
« предыдущая ветвь | форум | следующая ветвь »
COM порт, асинхронные чтение запись
REA © (2008-05-16 10:41:00)Помогите с вопросом. Уже мозг сломал.
Сделал чтение COM порта и периодически теряются байтики. В результате получился такой код:
FillChar(IO, SizeOf(IO), 0);
IO.hEvent := FIOEvent; // Overlapped
ToRead := 2; // Допустим 2
RdRes := ReadFile(idComm, Buf[1], ToRead, Bytes, @IO);
If (Not RdRes) And (GetLastError = ERROR_IO_PENDING) Then
RdRes := WaitForSingleObject(FIOEvent, 500) = 0; // Limit frame reading by 500 msec
If (RdRes) Then
RdRes := GetOverlappedResult(idComm, IO, Bytes, False);
If RdRes And (Bytes = ToRead) Then
и вот тут при RdRes = True число байт (Bytes) = 0.
Что я неправильно делаю?
REA (2008-05-23 12:55:00) [21]История продолжается: на одном компьютере все работает, а на другом выдает, что считано 0 байт, таймаутов не возникает, но после этого уже ничего читать не желает (всегда 0 байт).
REA (2008-05-19 20:08:00) [22]>среднее количество считываний при максимальной загрузке - 20 в мин.
Я думаю у меня столько же, но в секунду... Работает 12 лет на разных операционках 24 часа в сутки 365 дней в году, параллельно можно играть в Doom :)
REA (2008-05-19 20:05:00) [23]Похоже проблема решена:
установил общий таймаут на чтение ReadTotalTimeoutConstant = 100 и видимо когда ReadFile не может завершить чтение по межбайтовому таймауту он завершает по общему таймауту. В итоге таймаута WaitForSingleObject не возникает. Байты все на месте.
VICTOR_ (2008-05-19 19:57:00) [24]
> Почитал статью - принципиально только то, что они сначала
> дожидаются прихода хотя бы одного байта и потом вызывают
> ReadFile тем самым пытаясь исключить как я понял злополучной
> WaitForSingleObject. Но тоже без гарантии...
Я не знаю какую гарантию Вы хочете получить, так как Вы не описали полностью свою задачу.
Реально приложение, базирующееся на данном примере работает система
- чтение данных из компорта (~12байт) - код карточки
- работа 24*365
- срок реальной эксплуатации 9 мес.
- среднее количество считываний при максимальной загрузке - 20 в мин.
- использование данного приложения как COM-сервера(результат считывания возвращается в родительское приложение)
- на компьютере также крутится серверное приложение и MS SQL Server
Ассинхронный режим выбран в первую очередь по причинам, описанным в статье - нет реальной нагрузки на процессор и в то же время гарантированно считывается сигнал
REA (2008-05-19 18:17:00) [25]>Похоже что у тебя просто ошибка в 17-й строке, и система тут ни причем)
Это то и неприятно :( Убрал CancelIO, ошибка пропала. Попробовал сделать с WaitCommEvent перед ReadFile - тоже ничего не получается хорошего
REA (2008-05-19 18:16:00) [26]Почитал статью - принципиально только то, что они сначала дожидаются прихода хотя бы одного байта и потом вызывают ReadFile тем самым пытаясь исключить как я понял злополучной WaitForSingleObject. Но тоже без гарантии...
Сергей М. (2008-05-19 16:33:00) [27]
> Это вообще странно для API функции.
>
Похоже что у тебя просто ошибка в 17-й строке, и система тут ни причем)
REA (2008-05-19 16:01:00) [28]Еще одна странность: вызов функции CancelIO в случае возникновения таймаута приводит к Acess Violation. Это вообще странно для API функции.
VICTOR_ (2008-05-19 15:48:00) [29]Есть чудная статья на "Королевство Дельфи"
http://www.delphikingdom.com/asp/articles_forum.asp?ArticleID=1126
Реализовывал на ее основе приложение (чтение сигнала из COM-порта) - все работало корректно. Данные не терялись.
В процессе отладки также использовал программу Portmon
REA (2008-05-19 15:44:00) [30]Переделал чтение "одним куском" с прекращением по межбайтовому таймауту. Работать стало несколько стабильнее, хотя таймауты Wait по прежнему иногда возникают.
REA (2008-05-19 15:31:00) [31]А разница между "короткими" и "длинными" кадрами объсняется просто - при коротких кадрах WaitForSingleObject попросту не вызывается (ReadFile возвращает True) и все работает. Как только доходит до WaitForSingleObject работает через раз.
Evgeny V (2008-05-19 15:02:00) [32]
> REA (19.05.08 14:36) [40]
Отвечая на вопрос -сколько байт и когда читать, а также для удобной работы с портом посмотри следующие функции
WaitCommEvent - ждем нужных событий,
SetCommMask - подписаться на нужные нам события.
ClearCommError - обрати внимание на стурктуру COMSTAST и поле cbInQue.
REA (2008-05-19 15:01:00) [33]Вот нашел - может иметь отношение к теме. А может и не иметь...
http://support.microsoft.com/kb/q184072/
Пробовал сделать через макрос HasOverlappedIoCompleted. Как то не то...
Сергей М. (2008-05-19 14:41:00) [34]
> я же его открываю как CreateFile
И что ?
Первым параметром ты указал 'COMn', следовательно, требуешь от системы работу с этим файлом как с файлом коммуникационного дивайса ..
REA (2008-05-19 14:38:00) [35]А, в смысле DeviceIOControl только к файлам относится... А то можно двояко прочитать.
REA (2008-05-19 14:36:00) [36]Так я же его открываю как CreateFile. А как тогда узнать, сколько байт реально прочиталось?
Сергей М. (2008-05-19 12:58:00) [37]Да тут-то вроде бы нет засады - ты же как раз с коммуникационным дивайсом работаешь ..
REA (2008-05-19 12:51:00) [38]GetOverlappedResult
Windows Me/98/95: This function works only on communications devices or on files opened using the DeviceIoControl function.
уфф... засада за засадой
Сергей М. (2008-05-19 12:30:00) [39]
> ReadFileEx под 98 не работает
Да, не работает.
Но и упомянутых проблем с мультипроцессорностью там тоже быть не может, потому что оная поддерживается лишь в NT-линейке.
REA (2008-05-19 12:24:00) [40]>А зачем тогда асинхронка ?
См. [32]
ReadFileEx под 98 не работает. Попробовал под XP (+SleepEx) - где то виснет переодически...