使用Delphi读取文件时实现超时

时间:2010-11-17 01:46:23

标签: delphi file-io timeout delphi-2006

我有一个用Delphi 2006编写的应用程序,它定期从位于网络其他位置的磁盘文件(100Mb以太网)读取。偶尔通过网络读取需要很长时间(如20秒)并且应用程序冻结,因为读取是从主线程中的空闲处理程序完成的。

好的,我可以将读取操作放入它自己的线程中,但我想知道的是,是否可以为文件操作指定超时,这样你就可以放弃并去做其他事情,或者报告读取在20秒之后稍早陷入困境的事实。

function ReadWithTimeout (var Buffer     ;
                              N       : integer ; 
                              Timeout : integer) : boolean ;

begin
Result := false
try
    SetReadTimeout (Timeout) ;          //  <==========================???
    FileStream.Read (Buffer, N) ;
    Result := true ;
except 
    ... 
    end ;
end ;

2 个答案:

答案 0 :(得分:9)

当您致电File_Flag_Overlapped时,通过添加CreateFile标记打开asynchronous access的文件。当您致电TOverlapped时,请传入ReadFile记录,如果读取未立即完成,则该功能将提前返回。您可以通过在WaitForSingleObject结构中存储的事件上调用TOverlapped来控制等待读取完成的时间。您甚至可以使用MsgWaitForMultipleObjects等待;然后,只要读取完成消息到达,您就会收到通知,以先到者为准,因此您的程序根本不需要挂起。处理完消息后,您可以再次检查I / O是否已完成GetOverlappedResult,重新等待,或通过调用CancelIo放弃I / O.请务必仔细阅读所有这些功能的文档;异步I / O并非易事。

答案 1 :(得分:0)

将读取操作移到线程后,可以在读取之前存储timeGetTime返回的值:

isReading := true;
try
  startedAt := timeGetTime;
  FileStream.Read (Buffer, N);
  ...
finally
  isReading := false;
end;

并检查空闲处理程序是否花了太长时间。

例如:

function ticksElapsed( FromTicks, ToTicks : cardinal ) : cardinal;
begin
  if FromTicks < ToTicks
    then Result := ToTicks - FromTicks
    else Result := ( high(cardinal) - FromTicks ) + ToTicks; // There was a wraparound
end;

...

if isReading and ( ticksElapsed( startedAt, timeGetTime ) > 10 * 1000 ) // Taken too long? ~10s
then // Do something