Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "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. В 2 ReadResult = 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.53 MB
Время: 0.047 c
2-1159901078
MOVEz
2006-10-03 22:44
2006.10.22
WriteBinaryData


15-1156634027
Alex Konshin
2006-08-27 03:13
2006.10.22
Хозяева Земли. Кто они? Я прозрел.


8-1142759038
zxcv
2006-03-19 12:03
2006.10.22
выделение малоконтрастных объектов на изображении


2-1160053032
Pol
2006-10-05 16:57
2006.10.22
Виснет прога


2-1159642430
vegarulez
2006-09-30 22:53
2006.10.22
Как удалить ячейку из стринг грид?





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
Английский Французский Немецкий Итальянский Португальский Русский Испанский