用Delphi实现读取文件时的超时
我有一个用 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 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
打开文件以进行异步访问,方法是包含调用
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 callCreateFile
. Pass in aTOverlapped
record when you callReadFile
, 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 callingWaitForSingleObject
on the event you store in theTOverlapped
structure. You can even useMsgWaitForMultipleObjects
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 withGetOverlappedResult
, resume waiting, or give up on the I/O by callingCancelIo
. Make sure you read the documentation for all those functions carefully; asynchronous I/O isn't trivial.将读取操作移至线程后,您可以在读取之前存储 timeGetTime 返回的值:
并检查空闲处理程序是否花费了太长时间。
例如:
After you've moved the read operation to a thread, you could store the value returned by timeGetTime before reading:
and check in the idle handler if it's taken too long.
eg: