Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/delphi/8.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Delphi 德尔福/印地。Windows中的过程长时间延迟。连接_Delphi_Tcpclient_Delphi 2006_Indy10_Connection Timeout - Fatal编程技术网

Delphi 德尔福/印地。Windows中的过程长时间延迟。连接

Delphi 德尔福/印地。Windows中的过程长时间延迟。连接,delphi,tcpclient,delphi-2006,indy10,connection-timeout,Delphi,Tcpclient,Delphi 2006,Indy10,Connection Timeout,我的应用程序挂起在调用过程TIdStackWindows.Connect中。当TCP/IP地址存在时,没有问题,但如果没有,我就会挂起。IP地址是一个文本-不涉及DNS查找。我希望连接尝试在超时(TCPClient.ConnectTimeout)后失败。我已设置了1秒,但应用在此调用上最多挂起30秒(来自我的应用的调用没有线程化。我打算将TCP连接移动到线程,但长连接超时仍然是一个问题) 如果我在应用程序无响应时暂停Delphi IDE中的执行,我将定位在: ntdll.KiUserApcDis

我的应用程序挂起在调用过程
TIdStackWindows.Connect
中。当TCP/IP地址存在时,没有问题,但如果没有,我就会挂起。IP地址是一个文本-不涉及DNS查找。我希望连接尝试在超时(
TCPClient.ConnectTimeout
)后失败。我已设置了1秒,但应用在此调用上最多挂起30秒(来自我的应用的调用没有线程化。我打算将TCP连接移动到线程,但长连接超时仍然是一个问题)

如果我在应用程序无响应时暂停Delphi IDE中的执行,我将定位在:

ntdll.KiUserApcDispatcher:
7C90E450 8D7C2410         lea edi,[esp+$10]
然后我按F8键几次,直到看到堆栈帧。我当时在:

IdStack.TIdStack.RaiseSocketError(10038)
IdStack.TIdStack.RaiseLastSocketError
IdStack.TIdStack.CheckForSocketError(-1)
IdStackWindows.TIdStackWindows.Connect(912,'10.8.2.170',5001,Id_IPv4)
IdSocketHandle.TIdSocketHandle.Connect
IdIOHandlerStack.TIdConnectThread.Execute
:00451fc1 HookedTThreadExecute + $2D
Classes.ThreadProc($254B910)
System.ThreadWrapper($5456CB0)
:00451ea3 CallThreadProcSafe + $F
:00451f10 ThreadExceptFrame + $3C
:7c80b729 ; C:\WINDOWS\system32\kernel32.dll

我注意到,经过一番探索,这个话题已经获得了一些流量。常见的答案似乎是“把它放在一根线里”。我打算这样做,但长时间超时仍然会有问题。为什么连接超时不起作用?我正在使用Indy 10.5.5和Delphi 2006-如果我升级到Indy的最新版本,会有很多迁移吗?

阻塞套接字在API层没有连接超时的概念,因此Indy的
ConnectTimeout
是手动实现的超时。Indy在内部工作线程中调用
TIdStack.Connect()
,而
TIdTCPClient.Connect()
运行睡眠循环,等待该线程终止。如果循环检测到
ConnectTimeout
时间已过,它将关闭套接字,这将导致阻塞的
TIdStack.Connect()
立即退出,但这不是保证。在创建和终止线程时也存在操作系统开销。对1秒超时做出反应肯定不需要30秒,但另一方面,1秒通常太小。线程可能在1秒内甚至不会开始运行。通常应将
ConnectTimeout
设置为至少5-10秒,以便操作系统有足够的时间完成其工作。

阻塞套接字在API层没有连接超时的概念,因此Indy的
ConnectTimeout
是一个手动实现的超时。Indy在内部工作线程中调用
TIdStack.Connect()
,而
TIdTCPClient.Connect()
运行睡眠循环,等待该线程终止。如果循环检测到
ConnectTimeout
时间已过,它将关闭套接字,这将导致阻塞的
TIdStack.Connect()
立即退出,但这不是保证。在创建和终止线程时也存在操作系统开销。对1秒超时做出反应肯定不需要30秒,但另一方面,1秒通常太小。线程可能在1秒内甚至不会开始运行。通常,您应该将
ConnectTimeout
设置为最短5-10秒,以使操作系统有足够的时间完成其工作。

谢谢,雷米。我很怀疑,因为我看到了关于这个问题的其他评论,提到了30秒(延迟也在30秒的10毫秒之内-所以可能有一段源代码在某个地方有一个硬编码的30000毫秒延迟)。明天我会尝试更长的延迟,但我不抱希望。Indy的代码中没有硬编码的30秒延迟(但是,如果
ConnectTimeout
为0,则有硬编码的2分钟超时)。请参阅IdIOHandlerStack.pas中的
TIdIOHandlerStack.ConnectClient()
的实现。在
connect()
忙时运行的休眠循环在每次循环迭代中使用125毫秒(最大值)的休眠时间,但这将使API的延迟增加到30秒。请注意,如果您在主线程内调用
TIdTCPClient.Connect()
,并且您正在使用
tidAntizone
组件,则VCL的主消息队列在Indy之外可能会导致额外的延迟。说到30000毫秒的延迟,我想到的是Windows,而不是Indy!)谢谢你,雷米。我很怀疑,因为我看到了关于这个问题的其他评论,提到了30秒(延迟也在30秒的10毫秒之内-所以可能有一段源代码在某个地方有一个硬编码的30000毫秒延迟)。明天我会尝试更长的延迟,但我不抱希望。Indy的代码中没有硬编码的30秒延迟(但是,如果
ConnectTimeout
为0,则有硬编码的2分钟超时)。请参阅IdIOHandlerStack.pas中的
TIdIOHandlerStack.ConnectClient()
的实现。在
connect()
忙时运行的休眠循环在每次循环迭代中使用125毫秒(最大值)的休眠时间,但这将使API的延迟增加到30秒。请注意,如果您在主线程内调用
TIdTCPClient.Connect()
,并且您正在使用
tidAntizone
组件,则VCL的主消息队列在Indy之外可能会导致额外的延迟。说到30000毫秒的延迟,我想到的是Windows,而不是Indy!)