На главную Наши проекты:
Журнал   ·   Discuz!ML   ·   Wiki   ·   DRKB   ·   Помощь проекту
ПРАВИЛА FAQ Помощь Участники Календарь Избранное RSS
msm.ru
! user posted image
Пожалуйста, выделяйте текст программы тегом [сode=pas] ... [/сode]. Для этого используйте кнопку [code=pas] в форме ответа или комбобокс, если нужно вставить код на языке, отличном от Дельфи/Паскаля.

Соблюдайте общие правила форума

Следующие вопросы задаются очень часто, подробно разобраны в FAQ и, поэтому, будут безжалостно удаляться:
1. Преобразовать переменную типа String в тип PChar (PAnsiChar)
2. Как "свернуть" программу в трей.
3. Как "скрыться" от Ctrl + Alt + Del (заблокировать их и т.п.)
4. Как запустить программу/файл? (и дождаться ее завершения)
5. Как перехватить API-функции, поставить hook? (перехват сообщений от мыши, клавиатуры - внедрение в удаленное адресное прстранство)
... (продолжение следует) ...

Внимание:
Попытки открытия обсуждений реализации вредоносного ПО, включая различные интерпретации спам-ботов, наказывается предупреждением на 30 дней.
Повторная попытка - 60 дней. Последующие попытки - бан.
Мат в разделе - бан на три месяца...

Полезные ссылки:
user posted image MSDN Library user posted image FAQ раздела user posted image Поиск по разделу user posted image Как правильно задавать вопросы


Выразить свое отношение к модераторам раздела можно здесь: user posted image Rouse_, user posted image Krid

Модераторы: Rouse_, Krid
Страницы: (2) [1] 2  все  ( Перейти к последнему сообщению )  
> Вызов FileRead в асинхронном режиме , чтение файла в асинхронном режиме
    решил разобраться с вызовом функций WinApi в асинхронном режиме.
    покурил msdn, накидал такой примерчик:
    ExpandedWrap disabled
      procedure TForm1.DoAsyncLoad();
      var
        lReaded: Cardinal;
        lTransferred: Cardinal;
        lBuff: Pointer;
        lRes: Boolean;
        lErr, lErr2: Cardinal;
        lFileHandle: Cardinal;
        lOverlapped: TOverlapped;
      begin
       
        lFileHandle := CreateFile( PChar( edtFileName.Text ),
                                   GENERIC_READ, 0,
                                   nil, OPEN_EXISTING,
                                   FILE_ATTRIBUTE_NORMAL or FILE_FLAG_OVERLAPPED, 0 );
       
        if lFileHandle = INVALID_HANDLE_VALUE then
          RaiseLastOSError;
        try
          lReaded := 0;
          ZeroMemory( @lOverlapped, SizeOf( TOverlapped ));
          GetMem( lBuff, C_BLOCK_SIZE ); //используем большой буфер
          try
            repeat
              lReaded := 0;
              //обнуляем внутренние данные для нового вызова "перекрываемой" функции
              lOverlapped.Internal := 0;
              lOverlapped.InternalHigh := 0;
              //hEvent не задаю, так как нигде ожидать ничего не будем
              lRes := ReadFile( lFileHandle,
                                lBuff^,
                                C_BLOCK_SIZE,
                                lReaded,
                                @lOverlapped );
              if not lRes then
                lErr := GetLastError
              else
                lErr := ERROR_SUCCESS;
              if not lRes then
              begin //обрабатываем случаи, когда ReadFile = False
                case lErr of //проверка ощибки ReadFile
                  ERROR_IO_PENDING: //асинхронная операция
                  begin
                    lTransferred := 0;
                    repeat
                      lRes := GetOverlappedResult( lFileHandle,
                                                   lOverlapped,
                                                   lTransferred,
                                                   False );
                      if not lRes then
                        lErr2 := GetLastError;
                      if not lRes then
                        case lErr2 of //проверка ошибки  GetOverlappedResult
                          ERROR_IO_INCOMPLETE: Application.HandleMessage; //операция не завершилась? обработаем очередное сообщение
                          ERROR_HANDLE_EOF:
                          begin //файл кончился?
                            lReaded := 0; //ничего не прочитали
                            break; //выходим из внутреннего цикла
                          end;
                          else
                            RaiseLastOSError;
                        end;
                    until lRes; //пока не завершиться операция...
                    if lRes then
                      lReaded := lTransferred; //надо ли?
                  end;
                  ERROR_HANDLE_EOF: lReaded := 0; //если файл кончилсо, то выходим из цикла
                  else
                     RaiseLastOSError;
                end;
              end;//конец ветки, когда ReadFile = false
       
              if lRes then //здесь мы оказываемся в 2х случаях:1.ReadFile=true; 2.GetOverlappedResult в конце концов тоже вернул True
              begin
                //
                //что-то делаем с lBuff
                //
                lOverlapped.Offset := lOverlapped.Offset + lReaded; //сдвигаем
              end;
            until lReaded = 0;
          finally
            FreeMem( lBuff );
          end;
        finally
          CloseHandle( lFileHandle );
        end;
      end;

    все бы ничего... да только не всегда получается асинхронный вызов.
    в случае попытки чтения большого файла с винчестера функция FileRead ждет окончания чтения и возвращает true (
    и только в случае первой попытки обращения к съемному носителю срабатывает часть кода по работе с GetOverlappedResult...
    объясните знающие люди, в чем соль?!
    Сообщение отредактировано: MetalFan -
      неплохая статья про асинхронный ввод-вывод.
        Ahilles Спасибо конечно, но ничего нового статья мне не рассказала. вся информация есть в MSDN.
        да и примеры там все с флопом.
          Цитата MetalFan @
          все бы ничего... да только не всегда получается асинхронный вызов.

          Вернее - работает не пойми как. :D
          Цитата MetalFan @
          ExpandedWrap disabled
            //hEvent не задаю, так как нигде ожидать ничего не будем
                    lRes := ReadFile( lFileHandle,
                                      lBuff^,
                                      C_BLOCK_SIZE,
                                      lReaded,
                                      @lOverlapped);
          И?? Как же так - пытаешься использовать асинхронное чтение, а главный "семафор окончания отложенной операции" не создаешь? Далее :
          Цитата MetalFan @
          ExpandedWrap disabled
            if not lRes then
                      case lErr of //проверка ощибки ReadFile
                        ERROR_IO_PENDING: //асинхронная операция
          Это не ошибка - это признак того, что отложенная операция нормально стартовала. Здесь бы лучше запустить таймер и по его срабатыванию проверять - закончилась ли операция чтения (считано ли требуемое в ReadFile количество байт (WaitForSingleObject на эвент Overlapp'a должен вернуть WAIT_OBJECT_0 - если нет - то по GetOverlappedResult смотрим, сколько считано и сравниваем с размером файла, или по флагу ERROR_HANDLE_EOF принимаем решение сбросить дальнейшее чтение). Но лучше в любом случае перед считыванием получить размер файла, чтобы знать наверняка, сколько читать.)
            Цитата medved_68 @
            И?? Как же так - пытаешься использовать асинхронное чтение, а главный "семафор окончания отложенной операции" не создаешь?

            создавать и использовать его не обязательно. но даже его создание и использование положения не меняет.

            Цитата medved_68 @
            Это не ошибка - это признак того, что отложенная операция нормально стартовала.

            отложенная операция удачно "стартовала" только если GetLastError вернул ERROR_IO_PENDING.
            да, это не ошибка по сути.

            Цитата medved_68 @
            сколько считано и сравниваем с размером файла

            как ты заметил, файл читается не целиком, а кускакми


            з.ы. ты бы проверил работу кода, ибо пока ничего неясного ты не прояснил.
            Сообщение отредактировано: MetalFan -
              M
              MetalFan, я ваш вопрос отредактировал, код не подсвечивался. Там в теге CODE было CODE=delphi, а нужно - CODE=pas, ну это так, на будущее.


              Что касается вопроса - думаю, не нужно вызывать Application.HandleMessage; так как эта процедура в конце вызывает засыпание потока на неопределенное время - пока в очередь не поступит сообщение (Idle из которого вызывается WaitMessage). Как обрабатывать сообщения и одновременно дожидаться окончания ввода/вывода гляньте здесь:
              DeviceIOControl

              Там вся соль в функции MsgWaitForMultipleObjects
                Rose Сорри, с винграда скопировал и не заметил ньюанса с pas.
                по ссылке счас почитаю, спасибо

                Добавлено
                Цитата Rose @
                так как эта процедура в конце вызывает засыпание потока

                возможно... но не в этом проблема...
                если отрабатывает часть кода при FileRead = 0(False), то все ок.
                видимо я не совсем ясно расписал ситуацию и ты меня не понял :wacko:
                  Цитата
                  возможно... но не в этом проблема...


                  Все же попробуй переделать свой код на менер того, как в приведенной ссылке - Event заведи, MsgWaitForMultipleObjects используй, ProcessMessages вместо HandleMessage, все должно работать.
                    Rose Да нет! ты не понял... ветка кода с GetOverlappedResult и так работает на "ура"! но просто при чтении с ЖД FileRead всегда возвращает true.
                    при чем тут переделка кода?
                      Цитата
                      Rose Да нет! ты не понял...


                      Видимо действительно не понял. Вторая попытка :) Рискну предположить что дело вот в чем: ReadFile не обязана вернуть код ошибки ERROR_IO_PENDING в асинхронном режиме, и в справке об этом написано. Операция чтения может быть завершена достаточно быстро и в этом случае даже в асинхрооном режиме будет прочитано сразу все. Может у Вас именно этот случай? Или на ReadFile код надолго останавливается?
                        Rose можно на "ты"? ) а то "ты мне тут не выкайте")

                        Цитата Rose @
                        ReadFile не обязана вернуть код ошибки ERROR_IO_PENDING

                        именно! в коде обрабатываются оба варианта операции...
                        блин, наверное не очень его красиво структурировал...
                        дополнил код комментариями.


                        Цитата Rose @
                        Может у Вас именно этот случай? Или на ReadFile код надолго останавливается?

                        у меня именно этот случай при работе с HDD!!!!
                        как я уже ранее предположил, система скорее всего с жесткого считывает быстро, а вот мой 50Мб-йтный буфер заполняется как раз эти 0,5-1 секунды задержки...
                        Сообщение отредактировано: MetalFan -
                          Цитата
                          Rose можно на "ты"? ) а то "ты мне тут не выкайте")

                          Привычка от других форумов, где принято на "Вы" :ph34r: Перехожу на "ты".

                          Попробую твой код в ближайшее время, пока сам не увижу - наверное не пойму в чем проблема.
                            Rose угу, пасип.
                            да проблемы даже можно сказать и нет...
                            Цитата MetalFan @
                            как я уже ранее предположил, система скорее всего с жесткого считывает быстро, а вот мой 50Мб-йтный буфер заполняется как раз эти 0,5-1 секунды задержки...
                              Цитата
                              как я уже ранее предположил, система скорее всего с жесткого считывает быстро, а вот мой 50Мб-йтный буфер заполняется как раз эти 0,5-1 секунды задержки...


                              В общем, мои исследования привели меня к выводу, что все дело в кешировании файлов. Если флаг FILE_FLAG_NO_BUFFERING не установлен, то первое обращение к файлу может занять несколько большее время, а последующие происходят значительно быстрее. Если установлен - то механиз кеширования не применяется, однако при этом нужно соблюсти некоторые требования, о которых в справке написано. Короче, то, что у тебя происходит - это нормальное поведение.
                                Цитата Rose @
                                Если флаг FILE_FLAG_NO_BUFFERING не установлен

                                проверял и с ним и без него.
                                но еще один ньюанс у меня возник (с FILE_FLAG_NO_BUFFERING) - получаю Invalid Parameter вместо ERROR_HANDLE_EOF по достижению конца файла...

                                Добавлено
                                брр... возможно я не учел замечания в msdn по поводу выделения памяти под буфер
                                0 пользователей читают эту тему (0 гостей и 0 скрытых пользователей)
                                0 пользователей:


                                Рейтинг@Mail.ru
                                [ Script execution time: 0,0967 ]   [ 16 queries used ]   [ Generated: 16.10.25, 00:41 GMT ]