Mark Lobanov 1 Posted November 15, 2022 Hello I use TSslHttpCli in my backend built on DelphiMVCFramework for query external services. The TSslHttpCli object embedded into DelphiMVCFramework session and used each time then client called my endpoint. This call each time occurs in different thread. For certain reasons a can't create, use and free TSslHttpCli object each time in one thread context. I want to use thread context switching. Is this code safe? // initialization fClient: TSslHttpCli; ... fClient := TSslHttpCli.Create( nil ); fClient.MultiThreaded := True; // using if fClient.ThreadID = 0 then fClient.ThreadAttach; try fClent.Post(...); finally fClient.ThreadDetach; end; Share this post Link to post
FPiette 383 Posted November 15, 2022 At first glance it is not correct. The component is asynchronous. Calling one method will merely start the process in the background. You shouldn't detach the component from the thread before it has finished the operation you requested. You should remind that ICS components are asynchronous and doesn't require multi-threading to execute a lot of operations in parallel. Multi-threading is only useful if you have a large number (hundreds) of active communications simultaneously. Other operations that your application does may require multi-threading, for example lengthy SQL requests if they don't use an asynchronous programming model. Share this post Link to post
Mark Lobanov 1 Posted November 15, 2022 (edited) Since the code of [using] section is already executed in a separate thread, I use the synchronous Get method and not GetAsync I expect that in the finally section work of Get method will be completed 1 hour ago, FPiette said: At first glance it is not correct. What do you think would be the correct solution? Edited November 15, 2022 by Mark Lobanov Share this post Link to post
FPiette 383 Posted November 15, 2022 54 minutes ago, Mark Lobanov said: What do you think would be the correct solution? Use pure asynchronous operation. Share this post Link to post
Mark Lobanov 1 Posted November 15, 2022 (edited) 23 hours ago, Mark Lobanov said: code of [using] section is already executed in a separate thread have I use TSslHttpCli.PostAsync method ? separate thread is the TTask.Run() thread Edited November 16, 2022 by Mark Lobanov Share this post Link to post
FPiette 383 Posted November 15, 2022 Why in the first place do you create a thread? Is this a DelphiMVCframework requirement? Of course you can put your TSslHttpCli component in a thread. You should better create it at the beginning of the Execute method and free it before returning from the execute method (With a try/finally construct). Your thread need to have a message pump or call the one in TWSocket to work properly. There are a few samples of threads in ICS distribution. Multi-threading is always more complex and overkill with an asynchronous component. Share this post Link to post
Mark Lobanov 1 Posted November 16, 2022 Thank you, i saw the topic but is not my case. I can't create, run and free TSslHttpCli object in the same thread context for performance reasons and business flow. I have to create and free TSslHttpCli object within DelphiMVCFramework session and reuse it each time my endpoints are called. Each time my endpoint is called, new thread is created by DelphiMVCFramework engine with TTask.Run() and TSslHttpCli object is used in that thread context, each endpoint call - new thread, quite so DelphiMVCFramework works. I also can't use DelphiMVCframework's embedded HttpClient because it doesn't support TLS1.3 (( Share this post Link to post
Angus Robertson 574 Posted November 16, 2022 So effectively you want to use an external pool of TSslHttpCli objects from within your threads, rather than creating them as needed within the threads? So why use TSslHttpCli in the thread, why not just use one of the pool objects asynchronously, waiting in the thread for a semaphore to be set on competition? Windows actually creates a thread for async winsock operations, so there is no reason to use TSslHttpCli in the thread with all the messy stuff that goes with it. One of the ICS samples uses a pool of components and a queue to download all the elements on a web page. Angus Share this post Link to post
Mark Lobanov 1 Posted November 16, 2022 32 minutes ago, Angus Robertson said: So effectively you want to use an external pool of TSslHttpCli objects from within your threads, rather than creating them as needed within the threads? I have a similar pattern but easier One session, one client data (metadata, authorization, cookie etc.), one TSslHttpCli objects per session lifetime. No pool, no concurrent access to TSslHttpCli objects. My problem is that the TSslHttpCli object is created in one thread and is used each time in another thread. On each second call TSslHttpCli objects freezes in httpDnsLookup state. I do not want to use the asynchronous mode of the object yet. DelphiMVCFramework endpoint call is already in asynchronous mode within separate thread. Besides I don't have access to this threat execute method to add custom message handler. I added ThreadAttach/ThreadDetach code (look start message in this topic) and freezes gone but I not sure that this code is safe. François Piette thinks this is the wrong code Share this post Link to post
Angus Robertson 574 Posted November 16, 2022 Your solution may be easier than a pool, but it does not seem to work. ICS was not designed for cross thread use, use of threads within ICS is very rare, only for long ZLIB operations and a background mail queue. Angus Share this post Link to post
FPiette 383 Posted November 16, 2022 55 minutes ago, Mark Lobanov said: I added ThreadAttach/ThreadDetach code (look start message in this topic) and freezes gone but I not sure that this code is safe. François Piette thinks this is the wrong code What I meant is that it is not the best way to use ICS. What Angus suggested is a good idea. Have your pool of ICS components run asynchronously in a single thread dedicated to that. And from the session thread, call the pool thread to execute the HTTP requests. Use thread synchronization object to make sure no conflict with concurrent access from all session threads. You can use ThreadAttach and thread detach if you like but you must be sure to attache before socket is opened and before any communication take place and detach after all communication is done and socket closed. I'm not sure about OpenSSL work when used from several threads. Share this post Link to post
Mark Lobanov 1 Posted November 17, 2022 Ok, thank you, François and Angus Share this post Link to post