Главная страница
Top.Mail.Ru    Яндекс.Метрика
Текущий архив: 2008.06.29;
Скачать: CL | DM;

Вниз

Вопрос по overlapped - файлам   Найти похожие ветки 

 
homm ©   (2008-05-14 17:56) [0]

Есть такой код:

{
COMSTAT comstat;  //структура текущего состояния порта, в данной программе используется
   //для определения количества принятых в порт байтов
DWORD btr, temp, mask, signal; //переменная temp используется в качестве заглушки

//создать сигнальный объект-событие для асинхронных операций
overlapped.hEvent = CreateEvent(NULL, true, true, NULL);

//установить маску на срабатывание по событию приёма байта в порт
SetCommMask(COMport, EV_RXCHAR);            
while(условие) //пока поток не будет прерван, выполняем цикл
 {
  //ожидать события приёма байта (это и есть перекрываемая операция)
  WaitCommEvent(COMport, &mask, &overlapped);

  signal = WaitForSingleObject(overlapped.hEvent, INFINITE); //приостановить поток до прихода байта
  if(signal == WAIT_OBJECT_0)            //если событие прихода байта произошло
   {
    if(GetOverlappedResult(COMport, &overlapped, &temp, true)) //проверяем, успешно ли завершилась
       //перекрываемая операция WaitCommEvent
     if((mask & EV_RXCHAR)!=0)    //если произошло именно событие прихода байта
      {
       ClearCommError(COMport, &temp, &comstat);  //нужно заполнить структуру COMSTAT
       btr = comstat.cbInQue;                           //и получить из неё количество принятых байтов
       if(btr)                            //если действительно есть байты для чтения
       {
        ReadFile(COMport, bufrd, btr, &temp, &overlapped);     //прочитать байты из порта в буфер программы
       }
      }
   }
 }
CloseHandle(overlapped.hEvent);  //перед выходом из потока закрыть объект-событие
}


Разве после ReadFile не нужен либо WaitForSingleObject либо уничтожать overlapped.hEvent? Мне кажется что иначе функция возвратится до получения результата. Или я ошибаюсь?


 
Palladin ©   (2008-05-14 18:04) [1]


> Мне кажется что иначе функция возвратится до получения результата.

AFAIK, да, в случае провала ReadFile нужно проверить GetLastError на ERROR_IO_PENDING и дождаться WaitForSingleObject события чтения...


 
DiamondShark ©   (2008-05-14 18:15) [2]


> Разве после ReadFile не нужен либо WaitForSingleObject либо
> уничтожать overlapped.hEvent? Мне кажется что иначе функция
> возвратится до получения результата. Или я ошибаюсь?

После ReadFile нужно проверять результат функции и код ошибки.
Если функция возвратила 0 и GetLastError возвратила ERROR_IO_PENDING, то надо либо ждать WaitForSingleObject, либо звать GetOverlappedResult.

В принципе, этот код, скорее всего ;) будет работать, т.к. до вызова ReadFile в буфере драйвера порта есть какие-то байты, и функция ReadFile, скорее всего ;) завершится синхронно и успешно.

А вообще, в этом фрагменте кода overlapped нафиг не нужен. Аффтор кода запутался в трёх соснах, настроил overlapped в/в, а потом усиленно эмулирует синхронный в/в.

Выкинуть всё нафиг, настроить таймауты и юзать ReadFile в синхронном режиме.


 
homm ©   (2008-05-14 18:18) [3]

А возможно как-то выставить таймауты именно на WaitCommEvent? Что на ReadFile можно — знаю, но вроде не нужно.


 
DiamondShark ©   (2008-05-14 18:21) [4]


> homm ©   (14.05.08 18:18) [3]
> А возможно как-то выставить таймауты именно на WaitCommEvent?

Выкинуть всё -- значит выкинуть всё, включая WaitCommEvent.

Тут никакие евенты, кроме EV_RXCHAR не обрабатываются, значит хватит одной единственной ReadFile в синхронном режиме.
В случае таймаута ReadFile будет возвращать нулевое количество прочитанных байт.


 
homm ©   (2008-05-14 18:23) [5]

> [4] DiamondShark ©   (14.05.08 18:21)
> Тут никакие евенты, кроме EV_RXCHAR не обрабатываются,

Это тут не обрабатывается, а меня больше EV_RXFLAG интересует :)


 
homm ©   (2008-05-14 18:27) [6]

Хотя… Может таймаут на интервал между символами соседними поставить? Скажем 100мс. Минус будет в том, что чаще чем 10 раз в секунду ответ от порта получить не удастся… А так вроде получил нужный символ и сразу вернулся…


 
DiamondShark ©   (2008-05-14 18:32) [7]

Ты пойми, тут код бессмысленный даже без учёта особенностей ReadFile, WaitCommEvent и GetMeSomePizzaPleaseExW.

signal = WaitForSingleObject(overlapped.hEvent, INFINITE); сводит на нет все пляски с бубном вокруг overlapped в/в. Нафига тут overlapped, если поток всё равно безусловно блокируется?


 
DiamondShark ©   (2008-05-14 18:36) [8]


> А так вроде получил нужный символ и сразу вернулся…

А где гарантия, что в буфере до флагового символа не лежит мусор?
Всё равно придётся вычитывать буфер до нужного символа.


 
homm ©   (2008-05-14 18:37) [9]

Это в примере, у меня же нет :) В общем мой вариант:
function TCOMPort.GetResponce: String;
var
 Resive: array [0..255] of Char;
 Errs, NbChars: DWORD;
 Stat: TComStat;
 TransMask, signal: DWORD;
begin
 TransMask := 0;

 fOverlapped.hEvent := CreateEvent(nil, true, true, nil);
 WaitCommEvent(fHandle, TransMask, @fOverlapped);
 signal := WaitForSingleObject(fOverlapped.hEvent, TIMEOUT);
 CloseHandle(fOverlapped.hEvent);

 if (signal <> WAIT_OBJECT_0) then begin
     raise EReadPortTimeout.Create("Write Timeout");
 end;

 result := "";
 // здесь мне не понятно, возможно ли что проверка будет неудачной, если в качестве событий указано только одно — приход флага?
 if (TransMask and EV_RXFLAG) > 0 then begin
    ClearCommError(fHandle, Errs, @Stat);
    NbChars := Stat.cbInQue;
    ReadFile(fHandle, Resive, NbChars, NbChars, @fOverlapped);
    result :=  String(Resive);
 end;
end;


 
DiamondShark ©   (2008-05-14 18:50) [10]

После

> CloseHandle(fOverlapped.hEvent);

вызов

> ReadFile(fHandle, Resive, NbChars, NbChars, @fOverlapped);

страшно даже представить, к чему приведёт.

Закрывай хэндл эвента вместе с файловым хэндлом. Он тебе что, глаза мозолит?

Кстати, hEvent можно ставить в 0. Тогда в качестве хэндла для ожидания можно использовать файловый хэндл.


>  // здесь мне не понятно, возможно ли что проверка будет
> неудачной, если в качестве событий указано только одно —
> приход флага?
>  if (TransMask and EV_RXFLAG) > 0 then begin

Не вызван GetOverlappedResult. В принципе, содержимое TransMask не определено.

проверки результата ReadFile (и GetOverlappedResult, если ERROR_IO_PENDING) опять нет.


> result :=  String(Resive);

Ужос.

SetString(Result, Resive, NbChars);


 
homm ©   (2008-05-14 19:00) [11]

> [10] DiamondShark ©   (14.05.08 18:50)
> После
> > CloseHandle(fOverlapped.hEvent);
> вызов
> > ReadFile(fHandle, Resive, NbChars, NbChars, @fOverlapped);
> страшно даже представить, к чему приведёт.

Дак вроже должен привести к тому, что ReadFile вызовется синхронно и GetOverlappedResult и ERROR_IO_PENDING не понадобятся. Только сильно не ругайте, если ошибаюсь :)


> SetString(Result, Resive, NbChars);

Спасибо :)


 
DiamondShark ©   (2008-05-14 19:12) [12]


> Дак вроже должен привести к тому, что ReadFile вызовется
> синхронно

Это с мусорным-то хэндлом?
Нет. Там должен быть либо валидный хэнл, либо 0.



Страницы: 1 вся ветка

Текущий архив: 2008.06.29;
Скачать: CL | DM;

Наверх




Память: 0.5 MB
Время: 0.017 c
15-1211026442
Knight
2008-05-17 16:14
2008.06.29
Можно ли поставить IE7 на Win2k?


2-1212434898
Jeqa
2008-06-02 23:28
2008.06.29
учет


2-1212256392
Wildyt
2008-05-31 21:53
2008.06.29
Дан файл, состоящий из чисел


2-1212584820
TUserClass
2008-06-04 17:07
2008.06.29
Забацать DLL в EXE и распаковать ...


2-1212396147
Сергей
2008-06-02 12:42
2008.06.29
Как взять все записи четные пяти?