代码之家  ›  专栏  ›  技术社区  ›  rossmcm

用Delphi实现文件读取超时

  •  4
  • rossmcm  · 技术社区  · 14 年前

    我有一个用Delphi2006编写的应用程序,它定期从网络上其他地方(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 回复  |  直到 14 年前
        1
  •  9
  •   Rob Kennedy    14 年前

    打开文件 asynchronous access 包括 File_Flag_Overlapped 打电话时打旗子 CreateFile . 传入一个 TOverlapped 打电话时录音 ReadFile ,如果读取未立即完成,则函数将提前返回。您可以通过调用 WaitForSingleObject 当你在 重叠 结构。你甚至可以使用 MsgWaitForMultipleObjects 等待;然后在读取完成时通知您 消息到达,以先到者为准,因此您的程序根本不需要挂起。处理完消息后,可以再次检查I/O是否已完成 GetOverlappedResult ,继续等待,或通过调用放弃I/O CancelIo . 请确保仔细阅读所有这些函数的文档;异步I/O并不简单。

        2
  •  0
  •   Rob Kennedy    14 年前

    将读取操作移动到线程后,可以在读取之前存储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