Форум: "Прочее";
Текущий архив: 2008.06.29;
Скачать: [xml.tar.bz2];
ВнизВопрос по 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;
Скачать: [xml.tar.bz2];
Память: 0.48 MB
Время: 0.044 c