FloppyDesk 0 Posted July 18, 2019 (edited) Using 10 threads and after 100 iterations i got an exception. If i continue this exception, after 10 iterations it raises again, after VCL form frees and crashes. Quote First chance exception at $7B6D951C. Exception class $C0000005 with message 'access violation at 0x7b6d951c: read of address 0xfeeefeee' Quote First chance exception at $77101D6C. Exception class $C0000008 with message 'system exception (code 0xc0000008) at 0x6a5dfe8a' Quote First chance exception at $7B6D951C. Exception class $C0000005 with message 'access violation at 0x7b6d951c: read of address 0xfeeefeee' OnCreate Event Code: FHttpIcs := TSslHttpCli.Create(nil); FHttpIcs.MultiThreaded := True; FHttpIcs.SslContext := TSSLContext.Create(nil); FHttpIcs.ResponseNoException := True; FHttpIcs.FollowRelocation := True; FHttpIcs.LocationChangeMaxCount := 15; I tried to put FHttpIcs.SslContext := TSSLContext.Create(nil); in cycle (not onCreate event) but still no helps. Here is example of POST request, probably "same code" i have for GET requests. procedure TConnector.SubmitTokens; begin if (FThreadStatus = Terminated) then Exit; SetHeadersST(); SetPostParamsST(); FHttpIcs.RcvdStream := FResponseStream; FHttpIcs.Url := FUrl; try FHttpIcs.Post(); if (FHttpIcs.StatusCode > cBadRequest) or (FIsErrorConnection) then raise Exception.Create('err connection'); FHtmlResponse := FConnectorUtils.StreamToString(FResponseStream, TEncoding.UTF8); if (ContainsText(FHtmlResponse, 'true')) then // do some work else raise Exception.Create('err connection'); except on e: Exception do begin ReCheck(TMethods.SubmitTokensM); end; end; end; Edited July 18, 2019 by FloppyDesk Share this post Link to post
Angus Robertson 574 Posted July 18, 2019 Why do you need to run 10 threads, instead of 10 instances of TSslHttpCli in a single thread. That is how you use Indy which is blocking, not ICS which is none-blocking mostly. I would first ensure none of your threads access any visual components and ideally don't use Synchronize atall. I don't see a message loop anywhere in your thread, so nothing should work. You can use blocking calls in a thread, since it's doing nothing else. And a thread may be necessary if you are doing long processing like SQL database look-ups, although even then it's better to use a thread for only the SQL stuff and leave all ICS stuff in the main thread. Angus Share this post Link to post
FloppyDesk 0 Posted July 18, 2019 4 minutes ago, Angus Robertson said: I would first ensure none of your threads access any visual components and ideally don't use Synchronize atall. I use tthread.synchronize method, to update my "memo" for logging. I need replace the synchronization method? 6 minutes ago, Angus Robertson said: I don't see a message loop anywhere in your thread, so nothing should work. What do you mean about message loop? I have "while" loop in main thread which loops until "tthread not terminated flag set". I use 10 threads and 10 instances of TSslHttpCli 10 threads = 10 instances, each instance works on their own thread. 9 minutes ago, Angus Robertson said: You can use blocking calls in a thread, since it's doing nothing else. And a thread may be necessary if you are doing long processing like SQL database look-ups, although even then it's better to use a thread for only the SQL stuff and leave all ICS stuff in the main thread. I use multiple threads for speed up the request sending and get result to the software. If you can, send please a demo or give me aiming on something what can help me. Thank you in advance Angus. Share this post Link to post
Angus Robertson 574 Posted July 18, 2019 It is never a good ideal in high performance application to update a visual component like TMemo, scrolling the screen is expensive for heavy updates and will slow down or even stall your application, likewise calling Synchronous to do that stops your thread. I've been slowly updating ICS samples like OverbyteIcsIpStmLogTst1.pas so that log lines build a string buffer which is written to a TMeno from a timer every one or two seconds which is fine for most purposes. It is better to use Windows messages or even a socket to send logging to the main thread, effectively they become a non-blocking queue. Our tests with ICS indicate a single thread will handle at least two hundred simultaneous requests, provided don't block with SQL or start doing massive MD5sums or other horrible stuff. If you look at the OverbyteIcsMailQueue.pas unit, that has a thread to send emails from a queue, updating by the main thread, and shows how to use a message handler while the thread is waiting to do something. However if your thread only makes continual sync Post requests, you might get away without a specific message handler because ICS calls one itself waiting for the request to finish. But I'd still suggest creating an array of 10, 50, etc, TSslHttpCli all sharing the same event handlers, use Tag to identify which is calling an event and test that. This just works. Angus 1 Share this post Link to post
FPiette 383 Posted July 18, 2019 There are at least two important rules to write a multithread program which make use of ICS: 1) All ICS components must be created in the context of the thread. This is done for example in the start of thread's Execute method. 2) The thread must have a message pump also called message loop. There is one prebuilt in TWSocket. Have a look at OverbyteIcsThrdSrv1. pas (A unit in one of the ICS samples) and look at TClientThread.Execute. As Angus said, ICS is able to handle hundreds of connections in a single thread as far as ICS is concerned. Of course you may have heavy processing requiring a thread to not block the system. ICS is asynchronous, non-blocking and event-driven. It has all the required features to avoid multi-threading. And if you need multithreading, you should probably consider having tens or hundreds of ICS component in a single thread (For example, if you need 1000 component working simultaneously, use 5 threads each handling 200 components. Or if you have not that much simultaneous components, another design is to have a single thread for all ICS component and then a thread for each lengthy (computation or blocking operation) process. A good multithreading application is hard to write and hard to debug. 1 Share this post Link to post