Top.Mail.Ru
Мастера DELPHI, Delphi programming community Титульная страница Поиск, карта сайта Написать письмо 
| Новости | Поиск | FAQ | Статьи | Книги | Новости VCL |
| Форумы ЧАТ | Орешник | KOL и MCK |
Форумы -» Основная («Начинающим»)/ Базы / WinAPI / Компоненты / Сети / Media / Игры / Corba и COM / KOL / FreePascal / .Net / Прочее / RSDN.ORG

« предыдущая ветвь | форум | следующая ветвь »

ReadFile c Overlapped, ньюансы работы. [WinXP]


Страницы:   1 2

MetalFan ©   (2007-12-16 19:46:00) 

решил разобраться с вызовом функций WinApi в асинхронном режиме.
покурил msdn, накидал такой примерчик:

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
         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;
       if lRes then
       begin
         //
         //что-то делаем с lBuff
         //
         lOverlapped.Offset := lOverlapped.Offset + lReaded; //сдвигаем
       end;
     until lReaded = 0;
   finally
     FreeMem( lBuff );
   end;
 finally
   CloseHandle( lFileHandle );
 end;
end;

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


Игорь Шевченко   (2007-12-17 14:03:00) [21]

а вот пример в http://www.delphimaster.ru/articles/named_pipes/index.html
пользует асинхронный воод-вывод аккурат на API и вроде как работает...


DiamondShark   (2007-12-17 14:02:00) [22]


> else
>               RaiseLastOSError;

Это после вызова GetLastError?


> lOverlapped.Offset := lOverlapped.Offset + lReaded; //сдвигаем

а это зачем?! 8-(

А чего б тебе не юзать синхронные вызовы в отдельном потоке?
Код намного менее макаронистый получится.


MetalFan   (2007-12-16 19:57:00) [23]


> Riply ©   (16.12.07 19:49) [1]

:-P


Riply   (2007-12-16 19:49:00) [24]

После того как FileRead вернет True,
надо вызвать GetLastError, чтобы узнать причину удачи :)


Страницы:   1 2

Наверх

Титульная страница Поиск, карта сайта Написать письмо