Multithreading Delphi Rio 10.3.3与Indy 10.6.2.5366 TIdTCPServer线程问题

Multithreading Delphi Rio 10.3.3与Indy 10.6.2.5366 TIdTCPServer线程问题,multithreading,delphi,indy,delphi-10.3-rio,Multithreading,Delphi,Indy,Delphi 10.3 Rio,我正在使用Windows101903,DelphiRio10.3.3和Indy10.6.2.5366 我正在将使用TServerSocket的旧Windows服务应用程序升级到Indys TIdTCPServer。主要原因是我必须向应用程序添加IPv6支持 我遇到的问题是TIdTCPServer吃线程。对于到TIdTCPServer的每个连接,都会分配一个新线程(应该是这样的),但当客户端断开连接时,线程不会关闭 如果我同时连接两个客户端,IdTCPServer1.Contexts.LockLi

我正在使用Windows101903,DelphiRio10.3.3和Indy10.6.2.5366

我正在将使用TServerSocket的旧Windows服务应用程序升级到Indys TIdTCPServer。主要原因是我必须向应用程序添加IPv6支持

我遇到的问题是TIdTCPServer吃线程。对于到TIdTCPServer的每个连接,都会分配一个新线程(应该是这样的),但当客户端断开连接时,线程不会关闭

如果我同时连接两个客户端,IdTCPServer1.Contexts.LockList.Count=2和OnExecute事件将按其应该的方式每“周期”触发两次。然后,如果我断开一个客户端的连接,使IdTCPServer1.Contexts.LockList.Count=1,则OneExecute每个周期仅触发一次(也是应该的),但两个线程仍在运行。(我使用Windows taskmanager查看此信息)

我构建了一个简单的测试应用程序,每隔几秒钟随机连接和断开连接,启动了5个程序,当达到大约150个线程时,我的服务崩溃

以下是我的OnExecute活动:

procedure T#############.IdTCPServer1Execute(AContext: TIdContext);
var
 incomestring: string;
begin
 try
   if AContext.Connection.IOHandler.InputBufferIsEmpty then
   begin
    AContext.Connection.IOHandler.CheckForDataOnSource(100);
    AContext.Connection.IOHandler.CheckForDisconnect;
    if AContext.Connection.IOHandler.InputBufferIsEmpty then
     Exit;
   end;

   incomestring:= AContext.Connection.IOHandler.InputBufferAsString(en8bit);

   if length(trim(incomestring)) = 0 then
   begin
    exit;
   end;

   DataRead(incomestring, AContext); // Send data be processed
  except
   on E: Exception do
   begin
    if E is EIdException then
     raise // <- re-raise only Indy-specific exceptions end;
    else
    begin
     inc(ErrorCount);
     Logg('Error in IdTCPServer1Execute: ' + E.Message, ltError, AContext);
    end;
   end;
 end;
end;
procedure T##############。idtcpserver1执行(AContext:TIdContext);
变量
incomestring:字符串;
开始
尝试
如果AContext.Connection.IOHandler.InputBufferIsEmpty,则
开始
AContext.Connection.IOHandler.checkforDataSource(100);
AContext.Connection.IOHandler.CheckForDisconnect;
如果AContext.Connection.IOHandler.InputBufferIsEmpty,则
出口
结束;
incomestring:=AContext.Connection.IOHandler.InputBufferAsString(en8bit);
如果长度(修剪(incomestring))=0,则
开始
出口
结束;
数据读取(incomestring,AContext);//发送要处理的数据
除了
关于E:Exception-do
开始
如果E是异常,那么

raise/问题已解决!在DataRead()过程中,我使用TIdContext.Data成员存储指向具有额外信息的类的指针。在IdTCPServer1Disconnect上,我释放了额外的info类,但忘记将TidContext.Data设置为nil


因此,如果您曾经使用过TIdContext.Data成员,请记住在使用它时将其设置为nil!否则线程将永远运行。

您真的觉得有必要检查表单名称吗?您所能做的就是
T####
,而不仅仅是默认的
TForm1
?这可能是线程池的问题。当线程数接近150时,没有理由崩溃,除非系统资源不足。我认为你的问题在别处。嗨,你是否尝试使用连接的ReadTimeout属性?默认情况下,Indy不使用线程池。您必须通过将
TIdSchedulerOfThreadPool
分配给
TIdTCPServer.Scheduler
,显式启用该功能,否则将使用
TIdSchedulerOfThreadDefault
,而不是池。但是,您真的在调用
IdTCPServer1.Contexts.LockList()
?如果是,您是否也在调用
IdTCPServer1.Contexts.UnlockList()
?我在这段代码中没有看到任何会导致线程无法正确终止的内容,除非
DataRead()
Logg()
正在阻止线程,或者您正在锁定
上下文。所示代码之外的内容。感谢回复。是的,每次遍历LockList()时,我都在finally子句中调用UnlockList()。问题似乎出在数据读取过程中。我会进一步调查的。