1

I don't know if it's ok to access data from the main thread in the TIdTCPServer.OnConnect or OnDisconnect event. Is this method called from the main thread or other thread? I want to log the IP in a TMemo, and enable or disable some buttons.

Remy Lebeau
  • 555,201
  • 31
  • 458
  • 770
Marus Gradinaru
  • 2,824
  • 1
  • 26
  • 55
  • Do you know that you can easily test this yourself using the debugger? Set a breakpoint in such a event handler and read the thread ID/name from the debugger. – Andreas Rejbrand Sep 08 '20 at 12:47
  • https://i.postimg.cc/VLMxV2tp/screenshot-5.png what does this means ? – Marus Gradinaru Sep 08 '20 at 13:24
  • @MarusNebunu it means your `OnConnect` event handler is being called by a `TIdContext` object that is running in a worker thread that is represented by Indy's `TIdThread` class – Remy Lebeau Sep 08 '20 at 15:59

2 Answers2

3

TIdTCPServer is a multi-threaded component. Its OnConnect, OnDisconnect, OnExecute, and OnException events are all fired in the context of a worker thread that is represented by the event's TIdContext object. That thread manages the client TCP connection in the TIdContext.Connection property.

The OnListenException event is fired in the context of a different worker thread, which listens for client connections and creates the TIdContext threads.

So yes, TIdTCPServer event handlers must sync with the main thread when accessing UI controls and other shared data.

Remy Lebeau
  • 555,201
  • 31
  • 458
  • 770
1

I believe, its getting called in its own thread context.. Better to protect using Synchronize() or Queue()... Example:

procedure TMainForm.IdTCPSyncServerConnect(AContext: TIdContext);
var
  AClientIP: string;
begin
 
  AClientIP := AContext.Binding.PeerIP;
  TThread.Synchronize(nil,
    procedure
    var lItem : TListItem;
    begin
      Inc(FClientCount);
      lblClientConnections.Caption := IntToStr(FClientCount);
      lItem := lstClients.Items.Add;
      lItem.Caption := AClientIP;
      lItem.SubItems.Add(AClientIP);
      lItem.SubItems.Add(DateTimeToStr(Now));
    end
  );
end;
NamoRamana
  • 57
  • 7
  • 1
    In that kind of example, I would use `TThread.Queue()` instead, to avoid blocking the client thread so it is not dependent on the UI. And I would also store either the `TIdContext` in the `TListItem.Data` property, or the `TListItem` in the `TIdContext.Data` property, so that an `OnDisconnect` event can find the appropriate `TListItem` to remove it from the `TListView`. – Remy Lebeau Sep 08 '20 at 16:02