![]() |
| ||
|
|
Новости |
Поиск |
FAQ |
Статьи |
Книги |
Новости VCL
| | Форумы ЧАТ |
Орешник |
|
| |||
| |||
« предыдущая ветвь | форум | следующая ветвь »
ReadFile c Overlapped, ньюансы работы. [WinXP]
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, чтобы узнать причину удачи :)