5

我有一个用 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 ;
4

2 回答 2

9

通过在调用时包含标志来打开文件以进行异步访问。调用时传入一条记录,如果读取没有立即完成,函数会提前返回。您可以通过调用存储在结构中的事件来控制等待读取完成的时间。你甚至可以用等待;那么您可以在读取完成消息到达时立即通知您,以先到者为准,因此您的程序根本不需要挂起。处理完消息后,您可以通过调用再次检查 I/O 是否完成、继续等待或放弃 I/OFile_Flag_OverlappedCreateFileTOverlappedReadFileWaitForSingleObjectTOverlappedMsgWaitForMultipleObjectsGetOverlappedResultCancelIo. 确保您仔细阅读所有这些功能的文档;异步 I/O 并非易事。

于 2010-11-17T05:32:03.210 回答
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
于 2010-11-17T02:21:33.630 回答