Как убить все активные соединения и остановить IdTCPServer? Indy10 - PullRequest
0 голосов
/ 13 ноября 2018

при открытых соединениях IdTCPServer.Active:=false; вызывает зависание программы. Как убить все активные соединения и остановить 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;

1 Ответ

0 голосов
/ 13 ноября 2018

При открытых соединениях IdTCPServer.Active: = false;вызывает зависание программы.

Единственный способ, который может произойти, это если вы заблокируете сервер.

Это может произойти, если вы деактивируете сервер из контекста вашего основного интерфейса пользователя.поток, в то время как обработчики событий вашего сервера синхронно синхронизируются с основным потоком пользовательского интерфейса одновременно (TIdSync, TThread.Synchronize(), SendMessage() и т. д.).

Это также может произойтиесли ваши клиентские потоки делают что-то, что не является потокобезопасным, например, обращаются к пользовательскому интерфейсу без надлежащей синхронизации.

Деактивация сервера закрывает все активные сокеты и ожидает завершения их потоков.Но если один или несколько клиентских потоков заблокированы в ожидании основного потока пользовательского интерфейса или заблокированы каким-либо другим способом, а основной поток пользовательского интерфейса заблокирован в ожидании деактивации сервера, то это тупик, который приводит к зависанию программы.

Чтобы обойти это, вам нужно убедиться, что ваш серверный код является поточно-ориентированным, и что вы либо:

  • используете асинхронные syncs (TIdNotify, TThread.Queue(), PostMessage() и т. Д.), Чтобы клиентские потоки не блокировались в ожидании основного потока пользовательского интерфейса.

  • деактивировать сервер из рабочего потока, чтобы основной пользовательский интерфейспоток может свободно обрабатывать запросы синхронизации.

...