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.
Asked
Active
Viewed 168 times
1

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 Answers
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
-
1In 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