使用Indy时连接不会超时

6
我想从互联网上下载一个文件,我认为这应该是一个简单的任务。尝试了几种不同的方法后,我发现每种方法都有自己的缺点。主要问题如下:
  • 应用程序冻结直到下载完成
  • 如果网络连接丢失/服务器无响应,则应用程序永远冻结。

(详细信息请参见:

如何通过HTTP从互联网检索文件?
从互联网下载文件时连接不会超时 )

所以,最后我使用了来自几位专业人士的建议,使用“pro”库(如Indy)。然而,Indy并没有比我尝试过的代码片段更好(但它更大更难维护)。在使用Indy时,应用程序只会短暂地冻结,因此仍然可以(在某种程度上)使用。但是,在下载完成之前无法关闭应用程序(如果Internet连接断开,则永远无法关闭)。

其他人也报告了同样的问题:http://borland.newsgroups.archived.at/public.delphi.internet.winsock/200609/0609079112.html
https://forums.embarcadero.com/thread.jspa?threadID=25199&tstart=90

所以,我需要对TIDAntiFreeze进行一些黑客攻击才能使其工作?

此外,ConnectTimeout属性不被识别。

fIDHTTP := TIDHTTP.Create(NIL);
fIDHTTP.ConnectTimeout:=5000;

我应该放弃Indy并返回原始想法,在单独的线程中下载文件,并在其不响应时结束线程(至少这样我可以摆脱第三方库)吗?如果我这样做会有意想不到的副作用吗?

使用:Delphi 7,Indy 10.1.5 10.5(可能)。

谢谢


2
你尝试使用线程在后台下载文件了吗? - mjn
2
Indy 10.1.5非常老,目前的版本是10.5.7。 - mjn
2
无需安装,只需在运行时添加源路径并实例化组件即可。不幸的是,Indy安装脚本(FullDX.bat)不再起作用。 - mjn
1
我发现一些文章说TIdAntiFreeze不起作用。因此,我认为使用后台线程是唯一修复此问题的方法。 - mjn
1
'TIdAntiFreeze' 可以使用,但不建议使用。使用后台线程更好。 - Remy Lebeau
显示剩余2条评论
2个回答

4
您可能需要按照Indy的方式来使用Indy:使用线程。Indy是专门设计为在阻塞模式下工作的,因为大多数互联网协议都是如此(例如:对于HTTP,在协议层面上,您发送请求,然后读取响应。您不能同时发送和接收)。TIdAntiFreeze旨在帮助您使用一些Indy功能而不必处理线程;我从未使用过它,因为至少在概念上,它是一个丑陋的黑客。
如果您不想处理线程,那么您应该看看ICS - 它被设计为在异步模式下使用,无需线程。它不需要等效的TIdAntiFreeze,因为它不会阻塞。您启动下载并处理一些事件以获取进度和完成通知。ICS与Indy一样著名、专业且广泛使用。

经过绕了一圈线程,似乎它是唯一的解决方案!谢谢。 +1 - Gabriel

0

解决这些问题并不太困难。首先,您必须确保已正确处理错误处理。如果出现故障,请确保一切都能正确清理。此外,请确保下载代码是单独线程的一部分。如果有任何问题,您可以随时从主程序终止线程。以下是代码(仅用于下载,而非线程),对我来说运行良好。

with TDownloadURL.Create(nil) do
  try
    URL := 'myurltodownload.com';
    filename := 'locationtosaveto';
    try
      ExecuteTarget(nil);
    except
      result := false;
    end;
    if not FileExists(filename) then
      result := false;
  finally
    clear;
    free;
  end;

这并没有涉及到我们讨论的主要问题。引用:“应用程序会在下载文件之前冻结。” - Gabriel
请再次阅读我的帖子,并参考Cosmin Prund的答案。我们都在说你必须使用线程,否则无法防止这种情况发生。即使使用Indy,您也需要使用线程,没有其他方法。您说Indy对您的需求来说太笨重了,因此我提供了一个经过测试的替代方案,并同时说它必须是线程化的。我不明白为什么这个答案不能解决您的主要问题。回答:将其线程化。 - Daisetsu
Daisetsu,请查看此帖子:http://stackoverflow.com/questions/3526749/use-of-try-finally-except - Gabriel
当没有网络连接时,这需要正好21秒才会超时!所以解决超时问题是无用的。 - user1580348

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接