You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Linux环境下TIdHTTPServer调用Shutdown关闭时挂死问题求助

问题根因补充说明

该问题仅在TIdHTTPServer触发的核心原因是:TIdHTTPServer默认开启HTTP Keep-Alive机制,处理完请求后不会立刻断开连接,工作线程会处于等待新请求的阻塞状态,不会主动退出释放关联Yarn对象;而你此前使用的TIdTCPServer业务逻辑通常是处理完单任务即断开连接,工作线程执行完后会自动释放Yarn,因此关闭时不会触发死循环。

修复方案

方案1:关闭前主动断开所有活跃连接(无需修改Indy源码,推荐优先使用)

在设置IdHTTPServer1.Active := false之前,先手动关闭监听端口、断开所有已建立的连接,触发工作线程主动退出释放Yarn,示例代码如下:

procedure TYourServiceForm.StopHTTPService;
var
  idx: Integer;
  ctx: TIdContext;
begin
  // 先关闭监听端口,停止接收新连接
  IdHTTPServer1.Bindings.Close;
  // 倒序遍历所有活跃连接上下文主动断开
  for idx := IdHTTPServer1.Contexts.Count - 1 downto 0 do
  begin
    try
      ctx := TIdContext(IdHTTPServer1.Contexts.Items[idx]);
      if Assigned(ctx.Connection) then
        ctx.Connection.Disconnect;
    except
      // 忽略断开过程中可能抛出的连接已断开异常
    end;
  end;
  // 等待100-500毫秒给线程执行退出逻辑
  Sleep(200);
  // 再执行服务关闭操作
  IdHTTPServer1.Active := False;
end;

方案2:修改Indy源码修复调度器逻辑(一劳永逸解决同类问题)

找到Indy源码中IdSchedulerOfThread.pas文件的TIdSchedulerOfThread.TerminateYarn方法,补充等待线程退出、主动释放Yarn的逻辑,修改后代码如下:

procedure TIdSchedulerOfThread.TerminateYarn(AYarn: TIdYarn);
var
  LThread: TIdThreadWithTask;
begin
  if not Assigned(AYarn) then Exit;
  LThread := TIdYarnOfThread(AYarn).Thread;
  if Assigned(LThread) then
  begin
    // 发送停止信号
    LThread.Stop;
    // 最多等待3秒让线程正常退出
    if LThread.WaitFor(3000) = wrTimeout then
    begin
      // 超时强制终止线程
      LThread.Terminate;
      LThread.WaitFor;
    end;
  end;
  // 主动释放Yarn对象,会自动从活跃列表中移除
  FreeAndNil(AYarn);
end;

修改后重新编译Indy库即可,该修改对TIdTCPServer、TIdHTTPServer等所有基于该调度器的组件都生效,不会影响原有功能。

方案2:替换为线程池调度器规避问题

如果不想修改源码,也可以在初始化TIdHTTPServer时,手动指定使用线程池调度器TIdSchedulerOfThreadPool,该调度器的Yarn回收逻辑已处理了线程退出的等待逻辑,不会出现Yarn残留问题,示例代码如下:

uses
  ..., IdSchedulerOfThreadPool;

procedure TYourServiceForm.ServiceInit;
begin
  // 创建线程池调度器绑定到HTTPServer
  IdHTTPServer1.Scheduler := TIdSchedulerOfThreadPool.Create(Self);
  // 按需配置线程池大小
  TIdSchedulerOfThreadPool(IdHTTPServer1.Scheduler).PoolSize := 20;
  // 启动服务
  IdHTTPServer1.Active := True;
end;

内容的提问来源于stack exchange,提问作者Bart Kindt

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.05 18:48:01