Following on from this thread, I am trying to make a C++Builder XE5 application with:
- a main form
- a
TIdTCPClient
- a
TThread
for thatTIdTCPClient
's connection, which opens the socket, sends a request, then listens for multiple responses indefinitely - actions that occur on the socket will cause updates on the main form
I have been unable to find any examples; the examples linked from the Indy Demos page all do not use any threads in their clients, so far as I can see.
My questions are:
- Should the TIdTCPClient be on the main form (as a design time component), or should it be a member variable of the thread class?
- In the events fired by the TIdTCPClient , does the code in the event handlers (which are member functions of my main form) need to be Synchronized?
- Is it safe for both the main VCL thread and the client thread to make function calls on the TIdTCPClient object?
Currently I take actions on the main form in response to every event, and also in response to receiving data on the socket. At the moment my code is full of temporary variables and stub functions because Synchronize
requires a void(void)
closure and it is quite spaghetti. So I wonder if I am taking a fundamentally wrong approach.
Either will work fine. What is important is that you call
Connect()
and other I/O methods in the context of the worker thread (inside itsExecute()
method).Yes, if they are accessing UI controls, or other shared data that must be protected.
That depends on the particular calls (for instance, sending outbound data from the main thread while reading inbound data in the worker thread, at least while the client is connected), but I would not suggest you rely on that. You should just keep all of your client-related actions in the worker thread only.
You can use Indy's
TIdSync
/TIdNotify
classes to help you keep that spaghetti code better organized. For instance, derive a class fromTIdSync
, move your variables into it, and override its virtualDoSynchronize()
method to call your Form method(s) as needed. Then you can create an instance of thee class, populate its variables if needed, call itsSynchronize()
method, read its variables if needed, and then free it.