-
Помогите с вопросом. Уже мозг сломал.
Сделал чтение 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.
Что я неправильно делаю?
-
> RdRes := ReadFile(idComm, Buf[1], ToRead, Bytes, @IO);
>
> If (Not RdRes) And (GetLastError = ERROR_IO_PENDING) Then
А где обработка случая RdRes = True ?
> WaitForSingleObject(FIOEvent, 500)
> If (RdRes) Then
Почему 500 ? Откуда ты знаешь, что данные будут доступны не позднее пол-секунды ?
Где обработка случая RdRes = False ?
-
Может проще будет проверять сколько байт накопилось ?
Вот код (правда на С++)
size_t byte_in_port()
;
У меня это проверяется в цикле, и если за некоторое время ни чего не нападало - считаю, что передача закончена (не совсем правильно конечно).
А сам цикл, примерно такой:
...
if (m_state == state::eWrite)
};
/* read */
if (byte_in_port())
else
flush();
...
-
>А где обработка случая RdRes = True ?
Если ReadFile = True, то WaitForSingleObject как я понимаю уже ни к чему. Или нет?
Напоминаю, что ошибка замечена при RdRes = True. Т.е. из файла читается, потом отрабатывает WaitForSingleObject (таймаут не возникает) и GetOverlappedResult и считано 0 байт. Как будто какой то таймаут COM порта возник... При чем при синхронном чтении все работало достаточно стабильно.
>Откуда ты знаешь, что данные будут доступны не позднее пол-секунды ?
Должны быть практически сразу они. Там читается 2 байта на скорости 57600 и передатчик отвечает быстро.
>Может проще будет проверять сколько байт накопилось ?
Может... но и так работало в синхронном режиме
-
> Если ReadFile = True, то WaitForSingleObject как я понимаю
> уже ни к чему
Именно так.
> из файла читается, потом отрабатывает WaitForSingleObject
Зачем ожидание-то, если ReadFile = True ?
Сразу забирай данные из буфера в кол-ве lpNumberOfBytesRead
> Должны быть практически сразу они
Не надо делать никаких предположений.
Поставь INFINITE, если ожидание у тебя не в гуёвом потоке - гарантированно дождешься данные.
Или вызывай ф-цию ожидания в цикле с фиксированным сравнительно небольшим таймаутом, пока ф-ция не вернет True.
-
>Не надо делать никаких предположений
почему? за 500 мсек короткий кадр 102 процента должен дойти. А если не дошел, то транспортный протокол все восстановит (что он собственно и делает). INFINITE не люблю с детства.
>Зачем ожидание-то, если ReadFile = True ?
А и нету ожидания. Если ReadFile = True, то Wait не вызывается. Или GetOverlappedResult тоже в этом случае ни к чему? Сейчас проверю.
-
> Или GetOverlappedResult тоже в этом случае ни к чему?
Конечно ни к чему.
В этом и главная ошибка
-
Проверил. Может и ни к чему, но ошибка видимо не в этом. ReadFile = False, Wait = True, Overlapped = True, 0 байт из ожидаемых 2х принятно.
-
> Wait = True
Ф-ция ожидания вообще-то возвращает не булев результат, а код завершения.
Ты попросту не дожидаешься данных (о чем я тебе и сказал, спросив откуда взялось 500), потому как ф-ция вернула не нулевой результат, в то время как именно 0-й результат (см. константу WAIT_OBJECT_0) означает успешное завершение ожидания в течение указанного тобой периода таймаута.
-
Кстати, а каково состояние ивента на момент перед вызовом ф-ции ожидания ?
Ты вообще как создавал ивент, с какими параметрами ?
-
Не, там все как в исходниках написано. Т.е. проверяется на 0.
Таймаут там не возникает.
Event ручной, сбрасывается судя по MSDN сам при ReadFile.
-
> Т.е. проверяется на 0
А, да, вижу, есть такая проверка у тебя.
Что-то я не вижу про автосброс ивента ридфайлом ...
Ткни носом ?
-
ReadFile resets the event specified by the hEvent member of the OVERLAPPED structure to a nonsignaled state when it begins the I/O operation. Therefore, the caller does not need to do that.
Посмотрел COM монитором - байтики эти приходят, но уже потом, когда я решил, что это ошибка:
0.00000073 Geoscape.exe IOCTL_SERIAL_SET_WAIT_MASK Serial0 SUCCESS Mask: TXEMPTY - ждать пока последний байт ушел
0.00000312 Geoscape.exe IOCTL_SERIAL_SET_DTR Serial0 SUCCESS махнуть DTR
0.00001523 Geoscape.exe IRP_MJ_WRITE Serial0 SUCCESS Length 3: 51 00 4A записать
0.00000152 Geoscape.exe IOCTL_SERIAL_WAIT_ON_MASK Serial0 SUCCESS подождать
0.00000071 Geoscape.exe IOCTL_SERIAL_SET_WAIT_MASK Serial0 SUCCESS Mask: сбросить маску
0.00000447 Geoscape.exe IOCTL_SERIAL_CLR_DTR Serial0 SUCCESS снять DTR
0.00000279 Geoscape.exe IRP_MJ_READ Serial0 SUCCESS Length 2: 31 00 читать 2 байта
0.00000201 Geoscape.exe IRP_MJ_READ Serial0 SUCCESS Length 1: 52 читать все остальное - тут порядок
0.00000148 Geoscape.exe IOCTL_SERIAL_SET_WAIT_MASK
Serial0 SUCCESS Mask: TXEMPTY далее по кргу
0.00000381 Geoscape.exe IOCTL_SERIAL_SET_DTR Serial0 SUCCESS
0.00002319 Geoscape.exe IRP_MJ_WRITE Serial0 SUCCESS Length 3: 51 00 4A
0.00000156 Geoscape.exe IOCTL_SERIAL_WAIT_ON_MASK Serial0 SUCCESS
0.00000077 Geoscape.exe IOCTL_SERIAL_SET_WAIT_MASK Serial0 SUCCESS Mask:
0.00000518 Geoscape.exe IOCTL_SERIAL_CLR_DTR Serial0 SUCCESS
0.00000362 Geoscape.exe IRP_MJ_READ Serial0 SUCCESS Length 2: 31 00
0.00000195 Geoscape.exe IRP_MJ_READ Serial0 SUCCESS Length 1: 52
0.00000162 Geoscape.exe IOCTL_SERIAL_SET_WAIT_MASK Serial0 SUCCESS Mask: TXEMPTY
0.00000386 Geoscape.exe IOCTL_SERIAL_SET_DTR Serial0 SUCCESS
0.00002064 Geoscape.exe IRP_MJ_WRITE Serial0 SUCCESS Length 3: 51 00 4A
0.00000173 Geoscape.exe IOCTL_SERIAL_WAIT_ON_MASK Serial0 SUCCESS
0.00000069 Geoscape.exe IOCTL_SERIAL_SET_WAIT_MASK Serial0 SUCCESS Mask:
0.00000441 Geoscape.exe IOCTL_SERIAL_CLR_DTR Serial0 SUCCESS
181.90626013 Geoscape.exe IRP_MJ_READ Serial0 SUCCESS Length 2: 34 28 - а вот тут я не дождался
0.00000424 Geoscape.exe IOCTL_SERIAL_PURGE Serial0 SUCCESS Purge: RXCLEAR тут все забыть и по кругу
-
> байтики эти приходят, но уже потом
Что значит "потом" ?
-
Ну значит я ставлю точку остановки в отладчике где ошибка и туда попадает, байтов на этот момент еще нет. А потом они в мониторе видны - значит не потерялись в проводах.
-
А почему бы не воспользоваться ReadFileEx и колбэк-механизмом нотификации вместо овелэпа ?
-
Если не разберусь, то буду пытаться этот механизм задействовать. Что то мне подсказывает, что это не проще :)
Изменил код на такой:
RdRes := ReadFile(idComm, Buf[1], ToRead, Bytes, @IO);
If (Not RdRes) Then
Begin
If (GetLastError = ERROR_IO_PENDING) Then
Begin
RdRes := WaitForSingleObject(FIOEvent, 800) = 0;
If (RdRes) Then
RdRes := GetOverlappedResult(idComm, IO, Bytes, False)
Else
Begin
OutputDebugString(PChar('Wait bug: ' + SysErrorMessage(GetLastError)));
End;
End Else OutputDebugString(PChar('ReadFile bug'));
End;
и выдает он чаще всего вот что:
ODS: Wait bug: Протекает наложенное событие ввода/вывода
и кто бы сомневался, что оно протекает... только почему то не вытекает
-
ПРобуй так:
RdRes := ReadFile(idComm, Buf[1], ToRead, Bytes, @IO);
If not RdRes Then
Begin
If GetLastError = ERROR_IO_PENDING Then
Begin
while not (WaitForSingleObject(FIOEvent, 500) = WAIT_OBJECT_0) do Sleep(0);
Win32Check(GetOverlappedResult(idComm, IO, Bytes, False));
End Else
RaiseLastWin32Error;
End
-
Оно еще может возвратить WAIT_TIMEOUT, но мысль я понял. Тоже хотел так попробовать.
-
> Оно еще может возвратить WAIT_TIMEOUT
Может. Но выход из цикла только по WAIT_OBJECT_0
-
Выяснил что это все таки таймаут, но таймаут вне зависимости от его размера - т.е. хоть 20 секунд поставь. Переписал так:
If (GetLastError = ERROR_IO_PENDING) Then
Begin
RdRes := GetOverlappedResult(idComm, IO, Bytes, True); // А вдруг уже все?
If Not RdRes Then
Begin
WaitRes := WaitForSingleObject(IO.hEvent, 200);
RdRes := WaitRes = 0;
If (RdRes) Then
RdRes := GetOverlappedResult(idComm, IO, Bytes, True)
Else
Begin
OutputDebugString(PChar('Wait bug: ' + SysErrorMessage(GetLastError)));
End
End Else OutputDebugString('Wow');
End Else OutputDebugString(PChar('ReadFile bug'));
ээфект от этого заклинания получился странный: ошибок кажется не возникает, но и сообщение 'Wow' не выводит... Теперь придется проверить на одноядерных процессорах и на Win98 - сдается мне, что там оно себя может вести иначе...
-
А нет, все на месте :)
Если заменить
RdRes := GetOverlappedResult(idComm, IO, Bytes, True); на False, то выдает вот что:
ODS: Wait bug: Наложенное событие ввода/вывода не находится в сигнальном состоянии
Будем ломать дальше...
-
Все страньше и страньше. Таймаут теперь не возникает, но зато все как сначала: все отрабатывает Ok, но число байт = 0
Интересно еще вот что, если программа обменивается "пустыми" кадрами (там только заголовки без информации), то ошибок не возникает. Как только идет обмен "длинными" информационными кадрами возникает ошибка.
-
Дай определение "пустого" и "длинного" информационного кадра ..
-
> REA (16.05.08 10:41)
Могу переслать тебе книгу Павла Агурова. Самое, имхо лучшее пособие по работе с СОМ-портом. Скажи только куда.
-
>Дай определение "пустого" и "длинного" информационного кадра ..
ну пустой это байт 6, а длинный может 10 и более, но тоже не больше 16 наверно. Точнее не помню, но думаю это и не нужно.
>Могу переслать тебе книгу Павла Агурова. Самое, имхо лучшее пособие по работе с СОМ-портом. Скажи только куда.
Было бы здорово. Шлите на rea999<>hotmail.com
Только мне уже самому можно скоро будет книгу писать :)
-
> REA (17.05.08 20:06) [25]
Выслал.
-
> пустой это байт 6, а длинный может 10 и более
6 байт - это отнюдь не "пустой кадр".
Даже 1 байт, посланный дивайсом по прикл.протоколу, уже не есть "пустой кадр".
Может ты порт не должным образом инициализируешь ?
-
>6 байт - это отнюдь не "пустой кадр".
С точки зрения протокола кадрового уровня я имел ввиду. Поэтому в кавычках.
В синхронном режиме все работало. С появлением многоядерных компьютеров работать перестало (связано с записью и маханием DTR).
Ну может и неправильно инициализирую. Хотя 12 лет отработало уже...
Все равно непонятно где байты пропадают.
-
>Германн
Спасибо!
-
Поиграл с настройками порта - действительно при одних значениях таймаутов порта возникает именно таймаут при WaitForSingleObject, а при других таймаут не возникает, но число байт = 0
Сейчас сделал чтобы возникал таймаут (все таймауты порта установлены в 0, кроме межбайтового на чтение = 4мс). Ищем дальше...
-
А так ли уж необходим асинхронный оверлэп-режим ?
-
>А так ли уж необходим асинхронный оверлэп-режим ?
Дело в следующем: мне нужно дождаться ухода последнего байта, чтобы махнуть по протоколу DTR. Это можно сделать при помощи WaitCommEvent, но сама по себе эта функция таймаута не имеет и может зависнуть, если вызвать ее тогда, когда последний байт уже ушел. Что на многоядерных компьютерах и происходит. В Overlapped режиме можно результат проверить позже с таймаутом. Запись в порт в таком виде вроде работает.
-
Думаю, у тебя как минимум 2 верных варианта избавления от геморроя:
1. Работай с портом проверенным тобой способом, т.е. в синхронном блок-режиме, но в доп.потоке, если это непозволительно для основного.
2. Работай в оверлэпе (или с колбэками), но исключи возможность выполнения неконтролируемых тобой потоков своего процесса разными ядрами (см. SetProcess/ThreadAffinitiMask)
-
>Работай с портом проверенным тобой способом, т.е. в синхронном блок-режиме, но в доп.потоке, если это непозволительно для основного
там это и так в доп. потоке
>Работай в оверлэпе (или с колбэками)
пробую с колбэками. Насчет ThreadAffinitiMask это как то совсем уж сурово.
да в принципе оно и так работает - протокол кадры перезапрашивает, но не люблю такие фокусы - не известно как оно себя поведет на других компьютерах
-
> там это и так в доп. потоке
А зачем тогда асинхронка ? Или этот доп.поток у тебя кроме собственно транспорта еще чем-то важным озадачен ?
> Насчет ThreadAffinitiMask это как то совсем уж сурово
Ну а как ты хотел ?
На то и AffinitiMask, чтобы явно ткнуть систему носом в упомянутый запрет
-
>А зачем тогда асинхронка ?
См. [32]
ReadFileEx под 98 не работает. Попробовал под XP (+SleepEx) - где то виснет переодически...
-
> ReadFileEx под 98 не работает
Да, не работает.
Но и упомянутых проблем с мультипроцессорностью там тоже быть не может, потому что оная поддерживается лишь в NT-линейке.
-
GetOverlappedResult
Windows Me/98/95: This function works only on communications devices or on files opened using the DeviceIoControl function.
уфф... засада за засадой
-
Да тут-то вроде бы нет засады - ты же как раз с коммуникационным дивайсом работаешь ..
-
Так я же его открываю как CreateFile. А как тогда узнать, сколько байт реально прочиталось?
-
А, в смысле DeviceIOControl только к файлам относится... А то можно двояко прочитать.
-
> я же его открываю как CreateFile
И что ?
Первым параметром ты указал 'COMn', следовательно, требуешь от системы работу с этим файлом как с файлом коммуникационного дивайса ..
-
-
> REA (19.05.08 14:36) [40]
Отвечая на вопрос -сколько байт и когда читать, а также для удобной работы с портом посмотри следующие функции
WaitCommEvent - ждем нужных событий,
SetCommMask - подписаться на нужные нам события.
ClearCommError - обрати внимание на стурктуру COMSTAST и поле cbInQue.
-
А разница между "короткими" и "длинными" кадрами объсняется просто - при коротких кадрах WaitForSingleObject попросту не вызывается (ReadFile возвращает True) и все работает. Как только доходит до WaitForSingleObject работает через раз.
-
Переделал чтение "одним куском" с прекращением по межбайтовому таймауту. Работать стало несколько стабильнее, хотя таймауты Wait по прежнему иногда возникают.
-
-
Еще одна странность: вызов функции CancelIO в случае возникновения таймаута приводит к Acess Violation. Это вообще странно для API функции.
-
> Это вообще странно для API функции.
>
Похоже что у тебя просто ошибка в 17-й строке, и система тут ни причем)
-
Почитал статью - принципиально только то, что они сначала дожидаются прихода хотя бы одного байта и потом вызывают ReadFile тем самым пытаясь исключить как я понял злополучной WaitForSingleObject. Но тоже без гарантии...
-
>Похоже что у тебя просто ошибка в 17-й строке, и система тут ни причем)
Это то и неприятно :( Убрал CancelIO, ошибка пропала. Попробовал сделать с WaitCommEvent перед ReadFile - тоже ничего не получается хорошего
-
> Почитал статью - принципиально только то, что они сначала
> дожидаются прихода хотя бы одного байта и потом вызывают
> ReadFile тем самым пытаясь исключить как я понял злополучной
> WaitForSingleObject. Но тоже без гарантии...
Я не знаю какую гарантию Вы хочете получить, так как Вы не описали полностью свою задачу.
Реально приложение, базирующееся на данном примере работает система
- чтение данных из компорта (~12байт) - код карточки
- работа 24*365
- срок реальной эксплуатации 9 мес.
- среднее количество считываний при максимальной загрузке - 20 в мин.
- использование данного приложения как COM-сервера(результат считывания возвращается в родительское приложение)
- на компьютере также крутится серверное приложение и MS SQL Server
Ассинхронный режим выбран в первую очередь по причинам, описанным в статье - нет реальной нагрузки на процессор и в то же время гарантированно считывается сигнал
-
Похоже проблема решена:
установил общий таймаут на чтение ReadTotalTimeoutConstant = 100 и видимо когда ReadFile не может завершить чтение по межбайтовому таймауту он завершает по общему таймауту. В итоге таймаута WaitForSingleObject не возникает. Байты все на месте.
-
>среднее количество считываний при максимальной загрузке - 20 в мин.
Я думаю у меня столько же, но в секунду... Работает 12 лет на разных операционках 24 часа в сутки 365 дней в году, параллельно можно играть в Doom :)
-
История продолжается: на одном компьютере все работает, а на другом выдает, что считано 0 байт, таймаутов не возникает, но после этого уже ничего читать не желает (всегда 0 байт).
-
Проблема закрыта. Сделал задержку 1мс после записи, чтобы приемник не обрезал конец кадра. Почему то еще при чтении возвращалось больше байт, чем нужно. Не знаю откуда оно их берет, но я это проигнорировал и вроде работает в таком виде.
-
> Сделал задержку 1мс после записи, чтобы приемник не обрезал
> конец кадра.
А тайминги просто на операции чтения/записи никак проставить ?
> Почему то еще при чтении возвращалось больше байт, чем нужно.
Порт зачищай при открытии. Буфер порта, если не изменяет память, при открытии мусор содержит. По крайней мере , реально ставлкивался.
-
>А тайминги просто на операции чтения/записи никак проставить ?
См. выше про DTR и уход последнего бита
>Порт зачищай при открытии. Буфер порта, если не изменяет память, при открытии мусор содержит.
Зачищаю при ошибках, но там ошибок то не возникает. Все работает, но байт откуда то иногда берется больше, чем по идее устройство должно посылать. Контрольная сумма совпадает, а что за лишние байты не знаю...
-
> REA (23.05.2008 16:20:58) [58]
Если контрольная сумма совпадает, то это не лишнии байты.
-
> См. выше про DTR и уход последнего бита
Уход последнего байта ловят по TX_EMPTY. Список проблем, позволяет поставить диагноз, что у тебя всё-таки с указателями, где-то что-то не так, и NX срабатывает, или перезаписываешь, что-то не то.
-
Редкостное извращение: и таймауты и оверлапед.
Сам усложнил логику (совершенно необосновано) -- сам огрёб.
-
>Если контрольная сумма совпадает, то это не лишнии байты.
Контрольная сумма совпадает по числу байт из заголовка, остальные не учитываю. Работает нестабильно. Пока не могу сказать еще как - сам не понял.
>Уход последнего байта ловят по TX_EMPTY
Так и ловлю, но мне нужен еще уход последнего бита.
>у тебя всё-таки с указателями, где-то что-то не так
На одном компьютере все так, а на другом не так? Вряд ли...
>Сам усложнил логику (совершенно необосновано) -- сам огрёб.
Без таймаутов порта вообще не работает - не вылезает из WaitFSO. Даже по межбайтовому вылезает не всегда.
-
С лишними байтами разобрался - я переделал, чтобы оно читало не заданное количество байт, а все что есть, а по протоколу передатчик может послать сразу несколько кадров, а я про это уже забыл. Придется переделать обратно и добиваться чтобы работало... Причем таймаутов там никаких особых между кадрами нету и желательно чтобы WaitFSO возвращалось после чтения 2х начальных байт, а она этого делать не желает иногда... копаем дальше.
-
Переделал все примерно как было с начала. Проблема та же: ошибок при чтении и ожидании не возникает, но кадры куда то теряются - GetOverlappedResult возвращает 0 байт (если снова попытаться прочитать ReadFile, то все равно 0 байт и таймаутов никаких не возникает). Т.е. как бы данные есть, но их 0.
-
2 REA
Показал бы лучше полный код
-
Сейчас локальная функция чтения выглядит так:
Function ReadAsync: Boolean;
Var
IO: TOverlapped;
WaitRes: Integer;
ReadMore: Integer;
DummyBytes: DWORD;
Begin
FillChar(IO, SizeOf(IO), 0);
IO.hEvent := FIOEvent;
Bytes := 0;
ReadMore := ToRead; // Сначала 2 байта, потом остальное
Result := ReadFile(idComm, Buf[1], ReadMore, DummyBytes, @IO);
If (Not Result) Then
Begin
If (GetLastError = ERROR_IO_PENDING) Then
Begin
WaitRes := WaitForSingleObject(IO.hEvent, 200);
If WaitRes = WAIT_TIMEOUT Then
OutputDebugString(PChar('Timeout'));
Result := WaitRes = 0;
If (Result) Then
Result := GetOverlappedResult(idComm, IO, Bytes, False);
End Else OutputDebugString(PChar('ReadFile bug'));
End Else Result := GetOverlappedResult(idComm, IO, Bytes, False);
If Not Result Then
OutputDebugString(PChar('Wait bug: ' + SysErrorMessage(GetLastError)));
End;
Ошибок чтения не возникает, результат иногда = 0 байт.
-
> IO.hEvent := FIOEvent;
Лучше событие пересоздавать. А то при многопоточности, ерунда может выйти.
-
Ну и иде настройка порта? Я почему спрашиваю-та - ежель
> ошибок при чтении и ожидании не возникает, но кадры куда
> то теряются - GetOverlappedResult возвращает 0 байт (если
> снова попытаться прочитать ReadFile, то все равно 0 байт
> и таймаутов никаких не возникает). Т.е. как бы данные есть,
> но их 0.
то возможно чтение завершается по таймауту порта, тыж статус порта не проверяешь
-
>Лучше событие пересоздавать. А то при многопоточности, ерунда может выйти.
Пробовал, то же самое.
>Ну и иде настройка порта? Я почему спрашиваю-та - ежель
Уж какие я только не ставил вариации из таймаутов. Межбайтовый таймаут особенно не влияет на результат, а вот общий таймаут на чтение, если не поставить, то иногда будет подвисать в WaitFSO.
Сейчас стоит межбайтовый 1мс и общий 50 мс.
Действительно, в мониторе на операции чтения написано сейчас TIMEOUT, но откуда бы ему взяться? Если читать одним куском, а не как сейчас в два захода, то все работало. кажется...
-
> то все работало. кажется...
Креститься надо, када кажется:) Шютка, не обижайся. Ежель неуверенно чуйствуешь себе в таймаутах порта, то есть железный способ - отключить их нафиг. Далее ставишь маску эвентов SetCommEvent ждешь прихода байтов асинхронным вызовом WaitCommEvent с ...WaitFor... и нужным по логике приложения таймаутом или бесконечно. На срабатывание делаешь GetOverlappedResult и смотришь маску, которую передавал в WaitCommEvent. Ежель там EV_RXCHAR, вызываешь ReadFile и читаешь либо все, что пришло, либо сколько нужно до полного пакета. Далее цикл по новой - WaitCommEvent etc. Набрав целый пакет, вызываешь его обработку. Способ железобетонный, когда девайс шлет не шибко периодично, то пусто то густо. Если пакеты идут с хорошей периодичностью, то да, таймауты порта удобны, а иначе - ну их нахвиг.
-
> Ежель там EV_RXCHAR, вызываешь ReadFile
Вызываешь ClearComError - смотришь сколько пришло. Таймауты порта на старом железе и при хорошей длине кабеля - вещь важная.
-
>Ежель неуверенно чуйствуешь себе в таймаутах порта, то есть железный способ - отключить их нафиг.
Без них не работает в таком виде как сейчас. Неуверенно чувствую, потому что результаты получаются непредсказуемые. В принципе можно и так сделать, как ты описал, но проще сделать самому тогда уж буферизацию и читать одним куском с выходом из чтения по таймауту. Но медленнее будет. Хотя в этом случае придется и логику программы переделывать...
Пакеты идут сильно периодично - практически всегда, когда не передаются данные.
>Вызываешь ClearComError - смотришь сколько пришло. Таймауты порта на старом железе и при хорошей длине кабеля - вещь важная.
Железо нормальное хоть и самодельное. Кабель тоже не длинный - метра 3-4. Попробую ClearComError еще, но сдается мне монитор правильно показывает.
-
> Без них не работает в таком виде как сейчас
Естессно, нать как я писал.
> то иногда будет подвисать в WaitFSO.
Вот те и ответ - есть дыры между посылками. Неча читать она и висит. А ставишь таймаут - она по нему выкидыват. Тут ты ноль и читашь. Тут прынцип какой - не дергаться без нужды. Пришли байтики - читаем, нет - сопим в тряпочку то бишь спим. Вынеси всю эту беду в отдельный поток пусть се спит скока влезет. Можь ваще там синхронно читать, поставить таймаут милисек 500 - Terminate проверять и все дела. Хотя по мне асинхронка удобней даж в отдельном потоке, управляемость выше.
> Межбайтовый таймаут особенно не влияет на результат
Ты чет иль путаешь иль оценивашь результат. Должны влиять. Если канечна я чего по склерозности не путал:) Давай, кажи таймауты и описалово протокола. Будет время помедитирую.
-
>Вынеси всю эту беду в отдельный поток пусть се спит скока влезет.
так и есть
>Можь ваще там синхронно читать, поставить таймаут милисек 500
Так и было - см. выше. А похоже оно и в синхронном режиме кадры теряет, т.е. может проблема еще и в самой железке.
>Давай, кажи таймауты и описалово протокола.
Он длинный. Подобие SDLC
-
Удалено модератором
Примечание: Задай вопрос в своей ветке