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

发布于 2024-10-03 08:50:20 字数 586 浏览 7 评论 0原文

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

I have an app written in Delphi 2006 that regularly reads from a disk file located elsewhere on a network (100Mb ethernet). Occasionally the read over the network takes a very long time (like 20 secs) and the app freezes, as the read is done from an idle handler in the main thread.

OK, I could put the read operation into it's own thread, but what I would like to know is whether it is possible to specify a timeout for a file operation, so that you can give up and go and do something else, or report the fact that the read has snagged a bit earlier than 20 seconds later.

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

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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

戏舞 2024-10-10 08:50:20

打开文件以进行异步访问,方法是包含调用 CreateFile 时的 File_Flag_Overlapped 标志。调用ReadFile时传入TOverlapped记录,如果读取没有立即完成,函数将提前返回。您可以通过对存储在 TOverlapped 结构中的事件调用 WaitForSingleObject 来控制等待读取完成的时间。您甚至可以使用 MsgWaitForMultipleObjects 来等待;那么一旦读取完成或消息到达(以先到者为准),您就会收到通知,因此您的程序根本不需要挂起。处理完消息后,您可以使用 GetOverlappedResult 再次检查 I/O 是否完成,恢复等待,或通过调用 CancelIo 放弃 I/O。确保仔细阅读所有这些功能的文档;异步 I/O 并不是小事。

Open the file for asynchronous access by including the File_Flag_Overlapped flag when you call CreateFile. Pass in a TOverlapped record when you call ReadFile, and if the read doesn't complete immediately, the function will return early. You can control how long you wait for the read to complete by calling WaitForSingleObject on the event you store in the TOverlapped structure. You can even use MsgWaitForMultipleObjects to wait; then you can be notified as soon as the read completes or a message arrives, whichever comes first, so your program doesn't need to hang at all. After you finish processing messages, you can check again whether the I/O is complete with GetOverlappedResult, resume waiting, or give up on the I/O by calling CancelIo. Make sure you read the documentation for all those functions carefully; asynchronous I/O isn't trivial.

初见 2024-10-10 08:50:20

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

After you've moved the read operation to a thread, you could store the value returned by timeGetTime before reading:

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

and check in the idle handler if it's taken too long.

eg:

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
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文