SimonB 0 Posted 11 hours ago I am hoping someone can give me a few pointers on the correct way to use TSslHttpRest.RestRequest inside a thread. I am using ICS's TSslHttpRest (v9.5 / Delphi 12.3) inside a thread to talk to a REST API, the program has a few threads running at the same time that gather data in the background threads then post it off to diffrent APIs. To do this I am using RestRequest with the AsyncReq param set to False. http.RestRequest(httpPOST, 'https://sample.com', { * async * } False, param); This works 99.999% of the time and eveything is happy but on one users PC the threads will lockup about once a week or so, and I tracked it down to ICS, or more likely how I am using it. The DNS lookup is failing or timing out (not an ICS issue, its a hardware issue) and this is hanging ICS's DNS Lookup applicaton wide, not just the thread it fails in. Leaving them at the httpDnsLookup state. The tread that hangs goes to httpAborting inside the RestRequest. Here is a minimum example of how I am using TSslHttpRest, (actual code is inside a TThread) TThread.CreateAnonymousThread( procedure var http: TSslHttpRest; threadId: Cardinal; begin http := TSslHttpRest.Create(nil); try http.MultiThreaded := True; http.RestRequest(httpGET, 'https://jsonplaceholder.typicode.com/todos', False); //http.MessageLoop; finally http.Free; end; // Log the thread finishing threadId := GetCurrentThreadId; TThread.Synchronize(nil, procedure begin Memo1.Lines.Add(Format('Thread %d completed', [threadId])); end); end).Start; In the code for TWSocket it says Quote If you have to use multithreading, you have two possibilities: 1) Create your TWSocket from your thread's Execute method ... In both cases, you must set MultiThreaded property to TRUE. ... For both methods to work, you MUST have a message loop withing your thread. ... For your convenience, TWSocket has his own MessageLoop procedure. You can use it from your thread. But if I call TSslHttpRest.MessageLoop after TSslHttpRest.RestRequest it never returns. If I dont call it it all works are expected for the 99.999% of the time. But if I don't call it the call to TSslHttpRest.Free can hang when there has been a DNS issue. Due to TIcsAsyncDnsLookupThread.Execute calling SendMessage and waiting for the TSslHttpRest control to process it but without MessageLoop it never will. The call to TSslHttpRest.Free then tries to free its TIcsAsyncDnsLookupThread using UnRegisterIcsAsyncDnsLookup, but that theads is waiting for a responce form SendMessage so never finishes. and GThreadLocalStore is now locked so other threads can not use it. How can I use TSslHttpRest.MessageLoop and have it return so I can safely free the TSslHttpRest object? Share this post Link to post
Angus Robertson 678 Posted 8 hours ago The only ICS component that uses components within a thread is TMailQuThread in OverbyteIcsMailQueue.pas. It illustrates all the techniques needed to run within a thread. Essentially you are currently relying on synchronous mode for TSslHttpRest which has a message loop and a defined timeout, with some error handling. You should instead add events within your thread, use async mode (last parameter in RestRequest true), and then have your own message loop with FIcsWndControl.ProcessMessages after the request, in which you can watch the request state and cancel if DNS takes too long. Angus Share this post Link to post