Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Начинающим";
Текущий архив: 2007.05.20;
Скачать: [xml.tar.bz2];

Вниз

Время вызова колбэка FileIOCompletionRoutine   Найти похожие ветки 

 
Riply ©   (2007-05-02 01:04) [0]

Здравствуйте !
Дупустим, мы вытворяем следущее:
Вызываем
if ReadFileEx(........., @FOverLapRead, pCallBack) then inc(FOverLapRead.hEvent);
с таким колбэком:
procedure Overlapped_CallBack(cbError: DWord; BytesTransf: DWord; pOverLap: POVERLAPPED); stdcall;
begin
with pOverLap^ do
 if hEvent = bla-bla then bla-bla-bal
end;

Может ли получиться так, что наш колбэк успеет вызваться до inc(FOverLapRead.hEvent) ?
И аналогичная ситуация при использовании BindIoCompletionCallback.
Мы где-то "за_биндкомлетили" наш хэндл: BindIoCompletionCallback(FhPipe, Overlapped_CallBack, aFlag)
и вызываем:
if ReadFile(......., @FOverLapRead) then inc(FOverLapRead.hEvent);
Такой же вопрос:
Может ли колбэк успеть вызваться до inc(FOverLapRead.hEvent) ?
В случае положительного ответа на любой из этих вопросов, возникает еще один: как с этим бороться ?

P.S.
Я понимаю, что одно из решений: увеличивать hEvent до вызова ReadFile(Ex) и в случае неудачи - уменьшить.
Но я привела упрощенный пример. Вместо inc(FOverLapRead.hEvent) у меня довольно сложные действия,
которые хотелось бы выполнять только в случае успешного вызова ReadFile(Ex).


 
Riply ©   (2007-05-02 02:13) [1]

После тяжких раздумий, начинаю склоняться к тому, что в первом случае это невозможно,
пока нить-читатель не вызовет MsgWaitForMultipleObjectsEx. Так ли это ?


 
Riply ©   (2007-05-02 02:34) [2]

>[1] Riply © (02.05.07 02:13)
>в первом случае это невозможно, пока нить-читатель не вызовет MsgWaitForMultipleObjectsEx
Отнюдь не факт. А если вызовы идут из колбека ?
procedure Overlapped_CallBack(cbError: DWord; BytesTransf: DWord; pOverLap: POVERLAPPED); stdcall;
begin
if ReadFileEx(........., pOverLap, @Overlapped_CallBack)
 then inc(pOverLap.hEvent)
 else dec(pOverLap.hEvent);
end;

Совсем запуталась :)


 
Сергей М. ©   (2007-05-02 08:17) [3]


> Отнюдь не факт. А если вызовы идут из колбека ?


Именно факт.
Колбек будет вызываться системой в контексте тек.нити (той что вызвала Read/WriteEx) только при нахождении тек.нити в "тревожном" (alertable) состоянии, а оно как раз и наступает в рез-те вызова MsgWaitForMultipleObjectsEx.


 
Riply ©   (2007-05-02 09:21) [4]

>[3] Сергей М. © (02.05.07 08:17)
Привет :)
>Именно факт.
>Колбек будет вызываться системой в контексте тек.нити (той что вызвала Read/WriteEx)
>только при нахождении тек.нити в "тревожном" (alertable) состоянии,
>а оно как раз и наступает в рез-те вызова MsgWaitForMultipleObjectsEx.
Я, сначала, тоже так подумала, но следущий эксперимент показывает, что это не совсем верно:
Вызваем в нашей нити MsgWaitForMultipleObjectsEx, и, после этого запускаем "рекурсивный" читающий колбэк.
Если организовать "непрерывный поток данных" (сразу отправить, допустим, 100 сообщений по InBufferSize байт),
то наш колбэк самовызовется сто раз и только после этого один(!) раз сработает
MsgWaitForMultipleObjectsEx с результатом WAIT_IO_COMPLETION.
Т.е. колбэк не остановится и не вызовет WAIT_IO_COMPLETION,
пока не обработает (не занаю как назвать) пусть так: "все сообщения в очереди".
Если я правильно понимаю эту ситуацию, один раз вызвав MsgWaitForMultipleObjectsEx,
мы уже перевели нить в тревожное ожидание и, после этого возможны вызовы колбека подряд,
без перерывов на WAIT_IO_COMPLETION и новый вызов MsgWaitForMultipleObjectsEx


 
Сергей М. ©   (2007-05-02 10:24) [5]


> сразу отправить, допустим, 100 сообщений по InBufferSize
> байт


А зачем так делать ?
Это же ненормально ...

Если ты отправила сообщение, т.е. вызвала WriteFileEx, ты тем самым запустила асинхронную операцию вывода, о результатах выполнения которой тебе сообщит колбэк, который будет вызван не раньше ближайшего по времени перевода тобой отправляющей нити в трев.сост-е.

Вчитайся внимательно в справку:

If the WriteFileEx function succeeds, the calling thread has an asynchronous I/O (input/output) operation pending: the overlapped write operation to the file. When this I/O operation finishes, and the calling thread is blocked in an alertable wait state, the operating system calls the function pointed to by lpCompletionRoutine, and the wait completes with a return code of WAIT_IO_COMPLETION.

If the function succeeds and the file-writing operation finishes, but the calling thread is not in an alertable wait state, the system queues the call to *lpCompletionRoutine, holding the call until the calling thread enters an alertable wait state


И причем здесь, кстати, отправка, если речь сейчас идет о приеме ?

Для принимающей стороны нет никаких "сообщений", есть просто некий поток входящих данных, из которого она запрашивает для асинхронного чтения нужное кол-во байт. Колбэк-логика же при этом та же самая, что и при отправке.


 
Riply ©   (2007-05-02 11:40) [6]

>[5] Сергей М. © (02.05.07 10:24)
>> сразу отправить, допустим, 100 сообщений по InBufferSize байт
>А зачем так делать ?
>Это же ненормально ...
Может и ненормально, но я хочу добиться, чтобы сервер мог работать без всяких AV и прочих
"сюрпризов" вне зависимости от того кто, как, что и с какой частотой ему послал.
Ведь это некузяво, если сервер падает из-за клиента :)
Вот и гоняю его в различных условиях.

>И причем здесь, кстати, отправка, если речь сейчас идет о приеме ?
Речь, действительно, идет о приеме. Но чтобы его(прием) проверить, я со стороны клиента посылаю серверу "поток данных"
>Для принимающей стороны нет никаких "сообщений", есть просто некий поток входящих данных,
Значит я рано заявляла, что "с терминологией разобрались" :) Просто я представила себе поток,
состоящим из кусочков по InBufferSize, которые о обозвала "сообщениями".

>Вчитайся внимательно в справку:
Вот и получается, что при использовании "рекурсивного" читающего колбэка, до того как произойдет:
>When this I/O operation finishes, and the calling thread is blocked in an alertable wait state,
>the operating system calls the function pointed to by lpCompletionRoutine, and the wait completes with
>a return code of WAIT_IO_COMPLETION.

наш колбэк самовызывется столько раз, во сколько раз "входящий поток данных" превосходит размер буфера чтения,
без перевода "the calling thread is blocked in an alertable wait state". И только, когда поток данных завершился,
мы получаем однократное WAIT_IO_COMPLETION событие в нити.
Во всяком случае, такую ситуацию я стабильно воспроизвожу, а именно:
многократный вызов колбэка без события WAIT_IO_COMPLETION и повторного вызова MsgWaitForMultipleObjectsEx.
Поэтому САБЖ-евый вопрос остается пока открытым и для ReadFileEx :)


 
Сергей М. ©   (2007-05-02 11:52) [7]


> наш колбэк самовызывется столько раз, во сколько раз "входящий
> поток данных" превосходит размер буфера чтения


Ты в теле колбэк-процедуры анализируешь параметр BytesTransf, прежде чем принимать решение об очередном вызове ReadFileEx ?


 
Riply ©   (2007-05-02 12:06) [8]

> [7] Сергей М. ©   (02.05.07 11:52)
>Ты в теле колбэк-процедуры анализируешь параметр BytesTransf,
>прежде чем принимать решение об очередном вызове ReadFileEx ?
Да. И dwErrorCode и BytesTransf и еще сравниваю полученные данные с отправленными.
Все сходится(пока :).


 
Сергей М. ©   (2007-05-02 12:32) [9]

Пусть размер буфера чтения пайпа у тебя равен, к примеру, 4 байтам.
Пусть партнер послал тебе сообщение размером, скажем, 4*4=16 байт.
Пусть ты запросила к асинхронному чтению эти самые 16 байт вызовом ReadFileEx с указанием колбэк-процедуры и перевела нить в трев.состояние.

Тогда у тебя возникнет 4 вызова колбэк-процедуры, в каждом из которых параметр BytesTransf будет равен 4. Ты просто акумулируешь где-то в своем буфере эти 4 раза по 4 байта, при условии что dwErrorCode = 0.

После возврата из 4-го колбэка ты будешь выброшена системой из трев.состояния по событию WAIT_IO_COMPLETION, означающему что:
- либо все запрошенные тобой данные в размере 16-ти байт успешно приняты
- либо операция ввода была отменена вызовом CancelIo[Ex]

Посмотри пример от самих мелкомягких:

http://msdn2.microsoft.com/en-us/library/aa365601.aspx


 
Riply ©   (2007-05-02 22:09) [10]

>[9] Сергей М. © (02.05.07 12:32)
>Пусть размер буфера чтения пайпа у тебя равен, к примеру, 4 байтам.
>Пусть партнер послал тебе сообщение размером, скажем, 4*4=16 байт.
>Пусть ты запросила к асинхронному чтению эти самые 16 байт вызовом ReadFileEx с указанием
>колбэк-процедуры и перевела нить в трев.состояние.

Запросила то я 4 байта, а вот сколько реально(если рекурсия) прочитаю одному богу да отправителю известно :)
>Тогда у тебя возникнет 4 вызова колбэк-процедуры, в каждом из которых параметр BytesTransf будет равен 4.
>Ты просто акумулируешь где-то в своем буфере эти 4 раза по 4 байта, при условии что dwErrorCode = 0.
>После возврата из 4-го колбэка ты будешь выброшена системой из трев.состояния по событию WAIT_IO_COMPLETION, >означающему что:
>- либо все запрошенные тобой данные в размере 16-ти байт успешно приняты
>- либо операция ввода была отменена вызовом CancelIo[Ex]

Да. Все происходит именно так, как ты описал.
Значит будем считать установленным факт возможности нескольких вызовов колбэка подряд,
без выброса "системой из трев.состояния по событию WAIT_IO_COMPLETION".
А это оставляет САБЖ-вый вопрос актуальным и для ReadFileEx.
Мне, как и тебе, больше нравится рекурсивный метод чтения, но он ставит перед нами еще один вопрос:
Время отклика нашей нити становится непредсказуемым(теоретически, мы можем довольно
долго крутиться в цикле чтения), и пока мы там, нить не реагирует
ни на какие сообщения или события по MsgWaitForMultipleObjectsEx.
А нас (например, сервис менджер) запросил о нашем состоянии
и долго ждать ответа не собирается :) Прибъет ведь ненароком :)
Как бы ухитрится ему ответить в этой ситуации ?



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

Форум: "Начинающим";
Текущий архив: 2007.05.20;
Скачать: [xml.tar.bz2];

Наверх





Память: 0.5 MB
Время: 0.044 c
1-1174656308
KOSik
2007-03-23 16:25
2007.05.20
Рисование дуги окружности через три точки


2-1178034619
aht
2007-05-01 19:50
2007.05.20
DB Chart


15-1177322777
Zoop
2007-04-23 14:06
2007.05.20
Автоматические электомеханические варота.


2-1177756124
Ega23
2007-04-28 14:28
2007.05.20
Перехват события у TMyFrame


1-1174481739
kilya
2007-03-21 15:55
2007.05.20
MDI формы





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