Jump to content
FloppyDesk

Ics Multithreading exceptions

Recommended Posts

Posted (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'

Capture.thumb.PNG.e6afce1e99b59464b6858f0e747550bb.PNG

 

Quote

First chance exception at $77101D6C. Exception class $C0000008 with message 'system exception (code 0xc0000008) at 0x6a5dfe8a'

 

Capture111.thumb.PNG.707679cf51250bcbb38ac0565a315993.PNG

Quote

First chance exception at $7B6D951C. Exception class $C0000005 with message 'access violation at 0x7b6d951c: read of address 0xfeeefeee'

 

Capture123124.thumb.PNG.446240dbc0a1893f241ae6ea52463f5d.PNG

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 by FloppyDesk

Share this post


Link to post

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
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

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

 

  • Like 1

Share this post


Link to post

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.

  • Like 1

Share this post


Link to post

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
×