如何终止所有活动连接并停止 IdTCPServer?印地10

How to kill all active connections and stop IdTCPServer? Indy10

打开连接 IdTCPServer.Active:=假; 导致程序挂起。 如何终止所有活动连接并停止 IdTCPServer? 我正在尝试执行以下操作:

procedure TMyServer.Stop;
var
  List: TList;
  i: Integer;
begin
  List := Contexts.LockList;
  try
    for i := List.Count - 1 downto 0 do begin
      TMyContext(List.Items[i]).WaitDisconnect := True;
    end;
  finally
    Contexts.UnlockList;
  end;
  // Active := False;
  Timer.OnTimer := ProcTimer;
  Timer.Enabled := True;
end;

TMyContext = class(TIdServerContext)
public
  WaitDisconnect: Boolean;
end;


procedure TMyServer.Execute(AContext: TIdContext);
var
  Ctx: TMyContext;
begin
  Ctx := TMyContext(AContext);

  if not Ctx.WaitDisconnect then begin
     //read data
  else begin
    TMyContext(AContext).Connection.Disconnect;
  end;
end;

procedure TMyServer.ProcTimer(Sender: TObject);
var
  ClientsCount: Integer;
begin
  with Contexts.LockList do 
  try
    ClientsCount := Count;
  finally
    Contexts.UnlockList;
  end;

  if ClientsCount = 0 then begin
    Active := False;
    Timer.Enabled := False;
  end;
end;

With open connections IdTCPServer.Active:=false; causes the program to hang.

唯一可能发生的情况是服务器出现死锁。

如果您从主 UI 线程的上下文中停用服务器,而服务器的事件处理程序与主 同步 同步,则可能会发生这种情况 UI 同时线程(TIdSyncTThread.Synchronize()SendMessage() 等)。

如果您的客户端线程正在执行非线程安全的操作,例如在没有正确同步的情况下访问 UI,也可能会发生这种情况。

停用服务器会关闭所有活动套接字并等待它们的线程终止。但是,如果一个或多个客户端线程在等待主 UI 线程时被阻塞,或者死锁在其他线程上,并且主 UI 线程在等待服务器停用时被阻塞,那么这是一个挂起程序的死锁。

要解决这个问题,您需要确保您的服务器代码是线程安全的,并且您:

  • 使用异步同步(TIdNotifyTThread.Queue()PostMessage()等),因此客户端线程不是在主 UI 线程上阻塞等待。

  • 从工作线程停用服务器,以便主 UI 线程可以自由地正常处理同步请求。