Форум: "WinAPI";
Текущий архив: 2006.10.22;
Скачать: [xml.tar.bz2];
ВнизСобытие чтения из Com порта происходит когда в порте ничего нет Найти похожие ветки
← →
Kolan © (2006-05-30 18:37) [0]Здравствуйте,
Для чтения из порта использую вот такую ф-цию:
function TAnisochronousComm.Read(var Buffer: array of Byte;
NumberOfBytesToRead: Cardinal; TimeOut: Cardinal;
var IsTimeOutExpire: Boolean): Cardinal;
begin
Result := 0;
IsTimeOutExpire := False;
if FPortHandle <> INVALID_HANDLE_VALUE then
begin
if TimeOut <> INFINITE then
TimeOut := TimeOut * NumberOfBytesToRead;
ReadFile(FPortHandle, Buffer, NumberOfBytesToRead, Cardinal(Result),
@FOverlappedRead);
if WaitForSingleObject(FOverlappedRead.hEvent, TimeOut) = WAIT_OBJECT_0 then
GetOverlappedResult(FPortHandle, FOverlappedRead, Cardinal(Result), False)
else
IsTimeOutExpire := True;
end;
end;
Вызываю вот так:FBytesRead := FCommPort.Read(FBuffer, 1, INFINITE, IsTimeOut);
Вот тут я попросил прочесть 1 байт. СоответственноWaitForSingleObject
должна ждать пока не придет 1 байт, так? Но событие случается даже если в порт ничего не приходит. ИGetOverlappedResult(FPortHandle, FOverlappedRead, Cardinal(Result), False)
Result равен 0.
Эффекет проявляется при маленьких количествах считываемых байт, при больших 10, 20 такого нет.
Почему так получается?
← →
tesseract © (2006-05-30 21:28) [1]или пока не случиться timeout.
Возможно проблема в нём.
← →
Kolan © (2006-05-30 21:33) [2]Нет, нет это не он, проверял. Тем более:
FBytesRead := FCommPort.Read(FBuffer, 1, INFINITE, IsTimeOut);
Не думаю что он может сбыться...
← →
tesseract © (2006-05-30 22:00) [3]Кусок рабочего кода:
succ :=ReadFile(hCom,buffer,size,result,@REadOL);
if not succ then
begin
tmp:=GetLastError;
if tmp=ERROR_IO_PENDING then
if WaitForSingleObject(ReadOl.hEvent,WaitInt)=WAIT_OBJECT_0 then
GetOverlappedResult(hCom, ReadOL, result,true);
end; // if not succ
end // if fComWait
← →
Kolan © (2006-05-30 23:12) [4]
> Кусок рабочего кода:
Так и мой код работает, когда байты есть событие тоже приходит. А в чём разница?
← →
Сергей М. © (2006-05-31 09:15) [5]
> в чём разница?
Разница большая - в [3] есть анализ результата работы ф-ции ReadFile() на предмет ERROR_IO_PENDING, а в твоем коде этого анализа нет. А от этого результата напрямую зависит дальнейшее ветвление алгоритма (ждать или не ждать), которое у тебя напрочь отсутствует.
← →
tesseract © (2006-05-31 10:13) [6]и GetOverlappedReult не вернёться пока не закончен вывод.
В оригинале она вернёться (!!!!)
← →
han_malign © (2006-05-31 12:37) [7]FOverlappedRead.hEvent - как создаешь?
← →
tesseract © (2006-05-31 13:00) [8]
> ReadFile(FPortHandle, Buffer, NumberOfBytesToRead, Cardinal(Result),
> @FOverlappedRead);
Ещё одна - buffer[0] надо передавать - массив динамический.
← →
han_malign © (2006-05-31 14:22) [9]
> Ещё одна - buffer[0] надо передавать - массив динамический.
- не трынди, массив - открытый, а не динамический - var передается прямой ссылкой, а не косвенной...
← →
Kolan © (2006-05-31 15:10) [10]
(1) ReadResult := ReadFile(FPortHandle, Buffer, NumberOfBytesToRead, Cardinal(Result),
@FOverlappedRead);
(2)if not ReadResult then
begin
(3)LastError := GetLastError;
(4)if LastError = ERROR_IO_PENDING then
(5)if WaitForSingleObject(FOverlappedRead.hEvent, TimeOut) = WAIT_OBJECT_0 then
(6)GetOverlappedResult(FPortHandle, FOverlappedRead, Cardinal(Result), False)
else
IsTimeOutExpire := True;
end;
Вот вроде сделал как в tesseract © (30.05.06 22:00) [3].
Тоже самое.
Попадаем в 1. В 2ReadResult = False
.LastError = ERROR_IO_PENDING
- истинаWaitForSingleObject
- дожидаетсяCardinal(Result),
- Результат = 0..
Что за фигня..
Причем читает каждые 5 секунд(приблизительно).....
← →
tesseract © (2006-05-31 15:22) [11]
GetOverlappedResult(hCom, ReadOL, result,true);
<winApi reference>
bWait
Specifies whether the function should wait for the pending overlapped operation to be completed. If TRUE, the function does not return until the operation has been completed. If FALSE and the operation is still pending, the function returns FALSE and the GetLastError function returns ERROR_IO_INCOMPLETE.
</winApi reference>
Соответственно получаешь ERROR_IO_INCOMPLETE. Делай проверкe возвращаемого значения.
← →
Kolan © (2006-05-31 15:34) [12]Не очень понял:
GetOverlappedResult(FPortHandle, FOverlappedRead, Cardinal(Result), True);
LastError := GetLastError;
- ERROR_IO_PENDING
True - ничего не дало. И ошибка после GetOverlappedResult - ERROR_IO_PENDING.
А еще у меня есть кусочек статьи:
Замечу, что ожидать завершения ввода/вывода с помощью функции GetOverlappedResult не самое правильное решение. При работе с дисковым файлом операция завершится гарантированно, а при работе с последовательным или параллельным портом совсем не обязательно. Представьте, что Вы не настроили тайм-ауты последовательного порта, а подключенное устройство неисправно. GetOverlappedResult будет ждать вечно, так как нет способа указать максимальное время ожидания. Ждать завершения ввода/вывода лучше с помощью функций:
WaitForSingleObject
WaitForMultipleObjects
← →
Kolan © (2006-05-31 15:35) [13]Проблему я как-бы решил добавив проверку:
FCriticalSection.Acquire;
try
FBytesRead := FCommPort.Read(FBuffer, 1, INFINITE, IsTimeOut);
finally
FCriticalSection.Release;
end;
if FBytesRead > 0 then
Очень хочу именно понять вчём дело. Что не так я сделал...
← →
tesseract © (2006-05-31 15:56) [14]
> GetOverlappedResult будет ждать вечно, так как нет способа
> указать максимальное время ожидания. Ждать завершения ввода/вывода
> лучше с помощью функций
Бред.
Мы УЖЕ получили WaitForSingleObject. Теперь просто забираем буфер.
А у тебя случаем реакция на начальный символ не стоит?
Да и попробуй узнать есть-ли реально в буфере что-то с помощью ClearComError.
← →
Kolan © (2006-05-31 16:19) [15]
> Да и попробуй узнать есть-ли реально в буфере что-то с помощью
> ClearComError.
Узнаюvar
Errors: Cardinal;
begin
Result := 0;
if FPortHandle <> INVALID_HANDLE_VALUE then
begin
ClearCommError(FPortHandle, Errors, @FCommStat);
Result := FCommStat.cbInQue;
end;
end;
Нуль там...
А у тебя случаем реакция на начальный символ не стоит?
Незнаю... как и где проверить...
← →
tesseract © (2006-05-31 16:24) [16]Тогда не понял - ну нуль там, что же ты хочешь от ReadFile?
← →
Kolan © (2006-05-31 16:30) [17]
> Тогда не понял - ну нуль там, что же ты хочешь от ReadFile?
>
>
Я хотел бы, чтобы моя функцияRead
не читала 0 байт. Елси там ничего нет - 0, зачем читать, почему возникает событие?. Оноже должно вознинуть когда хотябы 1 байт прийдет...
Всеравно, что меня попросилибы: "Позвони когда пидет Вася", а я бы каждые 5 минтут звонил и говорил - "Вася не пришел". Спрашивается чё ты звонишь? Тебе же сказали только когда прийдёт позвонить.....
← →
tesseract © (2006-05-31 16:41) [18]
> Я хотел бы, чтобы моя функция Read не читала 0 байт. Елси
> там ничего нет - 0, зачем читать, почему возникает событие?
> . Оноже должно вознинуть когда хотябы 1 байт прийдет...
Так бы сразу и скакзал, а я мучаюсь. :-)
WaitCommMask используй на EV_RXCHAR.
← →
Kolan © (2006-05-31 16:45) [19]Ладно. Буду разбираться. Конечно пример с пояснениями мне бы очень помог... :)
Благодарю.
← →
tesseract © (2006-05-31 16:46) [20]
> Ладно. Буду разбираться. Конечно пример с пояснениями мне
> бы очень помог... :)Благодарю.
Могу выслать, но там прямой доступ к дровам и мало комментов, рискуашь ниасилить :-)
← →
Kolan © (2006-05-31 16:49) [21]НУ давай, буду благодарен... Хотя прямой доступ к дровам эту уж слишком...
← →
tesseract © (2006-05-31 16:53) [22]Подсекай.
← →
Kolan © (2006-05-31 16:55) [23]Угу. Благодарю за обсуждение :) Пошел разбираться.
← →
Evgeny V © (2006-06-01 14:03) [24]
> Елси там ничего нет - 0, зачем читать, почему возникает
> событие?.
Это возможно.
Событие может возникнуть при возникновении тайм-аута порта, смотрите COMMTIMEOUTS. Для настройки таймаутов см SetCommTimeouts
← →
atruhin © (2006-06-01 15:09) [25]
> но там прямой доступ к дровам
А зачем если не секрет? Что это дает?
← →
tesseract © (2006-06-01 15:19) [26]меньше загрузка процессора, этак раз в 10 меньше тактов уходит.
← →
Kolan © (2006-06-02 13:06) [27]Дааа, короче проблема в руках(моих) :)
Вот оказывается что было вконструкторе:FReadIntervalTimeout := 1000;
FReadTotalTimeoutMultiplier := 1000;
FReadTotalTimeoutConstant := 1000;
FWriteTotalTimeoutMultiplier := 1000;
FWriteTotalTimeoutConstant := 1000;
Поэтому, то событие и наступало.
Всех благодарю за ответы..
PS
Вот тебе и повторное использование кода... :)
Страницы: 1 вся ветка
Форум: "WinAPI";
Текущий архив: 2006.10.22;
Скачать: [xml.tar.bz2];
Память: 0.52 MB
Время: 0.039 c