我从Indy 10 TIdTCPServer下载了一些有趣的代码并编译并运行它。它有点乱,它可能需要工作,但它是一个有趣的东西的良好基础。至少我不必在这里发布所有代码。无论如何,我决定首先取消激活ExampleServer
,而不是仅仅在OnDestroy
中释放。所以我补充道:
procedure TServerPushExampleForm.FormClose(Sender: TObject);
begin
ExampleServer.Active := False; // bug here - never returns
end;
为了尝试对此进行调试,我将 IdCustomTCPServer.pas 添加到项目中并进入该项目。
TIdCustomTCPServer.StopListening;
行LListener.WaitFor;
引发异常此异常被TIdListenerThread.Run;
中的异常处理程序所困,但E.message
未在此处检索到,所以我不得不修改那里的代码来获取消息:
“操作已中止”
之后我进一步追踪它,但代码执行最终会回到同一个异常处理程序。
这是一个错误还是永远不要将Active属性设置为False?在我的测试中,如果我关闭应用程序并让RTL管理所有免费提供。无限循环不会发生(应用确实关闭)
答案 0 :(得分:3)
Indy使用阻塞套接字。
TIdListenerThread
运行循环,等待客户端连接。每次等待都是阻止操作。
当服务器被停用时,它会关闭其侦听套接字,导致挂起的套接字操作中止,然后终止侦听线程。中止异常在内部处理。
服务器的析构函数也设置Active=False
,因此无论是否显式停用,服务器都将被停用。
这个,如果它本身,不会导致你的挂起。通常,设置Active=False
的唯一方法是挂起,如果服务器事件处理程序尝试同步地与主UI线程同步,而主线程被阻塞等待服务器停用。经典的死锁场景。
但是在您链接的演示中似乎并非如此(所使用的唯一同步是异步的)。所以,还有其他事情可能会发生,你的调试尚未揭晓。应该没有挂起。