Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Stopping Delphi Indy threads without having to wait end Timeout

It's the first time I work on a multi-threads application with Delphi so all is still fesh for me, but I read a lot.

My thread is simple, to be short I just use Indy (IdHTTP) to GET the content of a web page and then I verify if the content contains a string. No problems here.

Now, to terminate threads I use a boolean with WHILE DO. It seems working but here is the problem : like I use a Timeout with Indy, sometimes I must wait the end of the timeout period before threads finish (when the server is not responding for example)...

It's annoying, especially when I use +200 threads. With other softwares using multi-threads and similar procedure, when I click "Stop" all is stopped in few seconds, and that is what I need.

I read that I should use an AntiFreeze, to allow IdHTTP to "read my instuctions"...

So, I'm a bit lost here. I don't think it's very necessary, but here is my code : http://pastebin.com/G7De8bgb

Thanks in advance for lights :)

Beny

like image 348
Beny Avatar asked Dec 27 '22 05:12

Beny


2 Answers

I've had a similar issue using Indy and webservices where the system we were talking too were unreliable at best ( I had to set read timeouts of 30 mins for some calls).

Since the Rio Calls ( and your IdHTTP ) calls are blocking your cannot canel/abort them directly.

You can however (if using different threads) disconnect the underlying socket which will cause an exception in the get/webcall.

I've done a quick hack to test the idea using just TIdHTTP and it appears to work as it does with the Rio.

In your main/controlling thread you need to call the IDHTTP.Disconnect, then catch the exception that will be raised in you thread. From looking at your code you are creating the IdHTTP in the Thread.Execute, you will have to move the declaration of that to the class's constructor to allow an Abort function on your thread class to simple disconnect the socket.

I've used Delph 7 and INDY10 just incase thats differnet to your setup.

Hope that helps

BTW

If anyone knows of a better/less agresive method I'd love to see that too.

like image 30
Dampsquid Avatar answered Apr 28 '23 13:04

Dampsquid


The class TidHTTP has an OnWork event. Use this event to cancel the data downloading or uploading. How to cancel with this event? Fire an Abort silent exception.

This is a pseudo code:

THTTPThread = class(TThread)
    private
        HTTPComponent: TidHTTP;
        procedure OnHTTPProgress(ASender: TObject; AWorkMode: TWorkMode;
                                     AWorkCount: Int64);
    published
        procedure execute();
end;

implementation
procedure THTTPThread.execute;
begin
    Self.HTTPComponent := TidHTTP.Create(nil);
    with HTTPComponent do
    begin
        OnWork := Self.OnHTTPProgress;
        Get('http://www.google.com');
    end;
end;

procedure THTTPThread.OnHTTPProgress(ASender: TObject; AWorkMode: TWorkMode;
  AWorkCount: Int64);
begin

    if Self.Terminated then
        Abort;
end;

Take into account that the stages on which OnWork are called are random. The event could be called at the middle of the request, at the begging or even at the end. The code above will work as if you press the stop button on the browser.

[UPDATE] Forget to mention that if then OnWork event is not called when the Thread is hanged out for a reply of the server, the use can use a timeout if the "last response" was received a specified milliseconds ago. Use GetTickCount for this.

like image 85
Christopher Ramírez Avatar answered Apr 28 '23 13:04

Christopher Ramírez