?
Solved

Cancel a TThread in middle of execution!

Posted on 2004-05-01
12
Medium Priority
?
776 Views
Last Modified: 2010-04-05
Ok, I got a little problem. I do work on an application which is going to download different stuff from the internet, and I got a little problem with the threads. I use some classes that can use up to 5 seconds to complete (like Connect), and it all runs after eachother (not a big loop for the entire thread, but a task, start to end). Therefore I can't use the easy, classic, Cancel := True, if cancel = True then Exit; way. I did try most procedures in TThread to cancel it, like Terminate, DoTerminate, Suspend, etc..., but none of them seems to cancel it. Is there some not too hard way to simply terminate/cancel, and then free the Thread without having to add extra If Cancel = True ..... code in the Execute procedure (I can't do that, because it doesn't run in a loop, and some of the procedures inside that thread takes time to do, and I can't do that If Cancel = True between each line of code). 400 points for this working answer.

Another extra question, worth 100 points, what is the difference between Destroy, and Free when I free a component, or class (like TMemoryStream)? Which of them frees it fully (returns just as many bytes as it took when I created it)?
0
Comment
Question by:imnotapro
  • 8
  • 4
12 Comments
 
LVL 4

Assisted Solution

by:ceoworks
ceoworks earned 2000 total points
ID: 10967839
Free method is doing the same work with Destroy but there is a little difference :

procedure TObject.Free;
begin
  if Self <> nil then
    Destroy;
end;

Free method is a procedure of TObject class. When you use TObject.Free, first of all it checks if this object nil or not then if it's not nil, it destroys the component. This protects you from to destroy a destroyed component and escape you from an error. This is the reason why Borland suggest you to use Free instead of Destroy. Because it's more secure.

When you free an object, it's not means that nil assigned to it. So most of the programmers using FreeAndNil(var Object) procedure, which has this code inside it :

procedure FreeAndNil(var Obj);
var
  Temp: TObject;
begin
  Temp := TObject(Obj);
  Pointer(Obj) := nil;
  Temp.Free;
end;

Take a look at this, first of all 'nil' assigned to the object and then this object frees.

Cheers,

Oktay
0
 
LVL 4

Expert Comment

by:ceoworks
ID: 10967859
I'm not sure if i completely understand your question but you may think to use this code :

MyThread.FreeOnTerminate := True;
..
MyThread.Suspend;
MyThread.Terminate;
..
0
 

Author Comment

by:imnotapro
ID: 10967947
Ceoworks: Thanks for this nice answer. I'll accept your answer (guarantied) when I get the other answer (it's not possible to accept one at time).

Ceoworks again: Okay, I'll try that now.
0
Technology Partners: We Want Your Opinion!

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

 
LVL 4

Expert Comment

by:ceoworks
ID: 10967953
Ohh i understand what you meant when you say that stop execution of internet related things and free them. In 5 min, i'll go back to home and if i'll have time i'll try to develop a little sample for you.

Cheers,

Oktay
0
 

Author Comment

by:imnotapro
ID: 10968029
Okay, with the first question I need a bit more help. Take a look at this:

procedure Tdownloader.Execute;
begin
  ...
  //Here we get some instance where this download fails, and therefore I want it to kill itself, and free completly
  //The ID variable is declared in the Type, and contains (100% sure) it's own number in it's array of Tdownloader.
  KillDownloadHandle(ID);
  ...
end;

procedure KillDownloadHandle(ID: Integer);
begin
  //Here I tried what you suggested:
  download[ID].Suspend;

  freeandnil(download[ID]);
end;


I think that part is a bit dumb, cuz when the thread is going to kill itself, I just proved that it stops on Suspend, which again causes that it never runs freeandnil. Will FreeOnTerminate make sure it gets freed then? Or should I do something like this:

procedure KillDownloadHandle(ID: Integer; Myself: Boolean);
begin
  if myself=True then
  begin
    exit;   //Simply let FreeOnTerminate free it
  end else begin
    download[ID].Suspend;
    freeandnil(download[ID]);
  end;
end;


Would that make that part memoryleakfree (I know it frees the entire application automatically on exit, but this application can run LONG without being closed, so everything should be leak-free)?
0
 
LVL 4

Accepted Solution

by:
ceoworks earned 2000 total points
ID: 10968047
Sorry I'm not sure and i don't have time to try this example but you can design your thread class like this :

unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, IdBaseComponent, IdComponent, IdTCPConnection, IdTCPClient;

type
  TForm1 = class(TForm)
    IdTCPClient1: TIdTCPClient;
    procedure FormCreate(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

  TMyThread = class(TThread)
  private
    FSocks: array[0..2] of TIdTCPClient;
  protected
    procedure Execute;
  public
    constructor Create(ConnIP: string; ConnPort);
    procedure StopConnections;
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

procedure TForm1.FormCreate(Sender: TObject);
begin

end;

{ TMyThread }

constructor TMyThread.Create(ConnIP: string; ConnPort);
var
  i: integer;
begin
  for i := 0 to 2 do
  begin
    FSocks[i] := TIdTCPClient.Create(nil);
    FSocks[i].Host := ConnIP;
    FSocks[i].Port := 381;
    FSocks[i].Connect;
  end;
  inherited Create(True);
  FreeOnTerminate := True;
end;

procedure TMyThread.Execute;
begin
  // internet stuff here
  Terminate;
end;

procedure TMyThread.StopConnections;
var
  i: integer;
begin
  Suspend;
  for i := 0 to 2 do
  begin
    FSocks[i].Disconnect;
    FreeAndNil(FSocks[i]);
  end;
  Terminate;
end;

end.

For to stop your connections with this class, all you need to do is calling StopConnections. Then after to close all the connections, thread will terminate itself.

I hope these helps..

Cheers,

Oktay Sancak
0
 

Author Comment

by:imnotapro
ID: 10968078
Okay, that helped a lot :). One more thing, what's the difference between Suspend and Terminate here?

The points are yours :).
0
 
LVL 4

Expert Comment

by:ceoworks
ID: 10968096
Before i see your last post, i had send this answer. I can give you a detailed answer after 1-2 hour because i'm ready to go back to home now. Until that time, you may wants to try the logic of my last code.. Sorry but I really hurry and i don't have time to think about your last code. I'll try to make it all clear for you then.

Cheers,

Oktay

0
 
LVL 4

Expert Comment

by:ceoworks
ID: 10968110
Suspend stops the execution of your thread then it become safe for you to Disconnect and FreeAndNil your sockets. At the final you are calling Terminate and then your thread frees itself.

I'm glad to hear that you problem solved :)

Have a nice day,

Oktay Sancak
0
 
LVL 4

Expert Comment

by:ceoworks
ID: 10968537
Sorry i was hurried when i was typing this code so it needs a little fix :

  TMyThread = class(TThread)
  private
    FSocks: array[0..2] of TIdTCPClient;
  protected
    procedure Execute;
  public
    constructor Create(ConnIP: string; ConnPort);
    procedure StopConnections;
  end;
 
  should be :

  TMyThread = class(TThread)
  private
    FSocks: array[0..2] of TIdTCPClient;
    procedure Execute; override; // override
  public
    constructor Create(ConnIP: string; ConnPort: integer); // and type of ConnPort
    procedure StopConnections;
  end;

Rgds,

Oktay
0
 

Author Comment

by:imnotapro
ID: 10968883
Thanks, you've really been helpful, you deserve those 500 points :).

I got a system very similar to yours with a few modifications (to suit my previous setup), and it's all working now, 100% failsafe. Thanks :).
0
 
LVL 4

Expert Comment

by:ceoworks
ID: 10969317
To be helpfull is more important than points. I'm really glad to hear that your problem solved.. :)

Have a nice day,

Oktay Sancak
0

Featured Post

Free Tool: Subnet Calculator

The subnet calculator helps you design networks by taking an IP address and network mask and returning information such as network, broadcast address, and host range.

One of a set of tools we're offering as a way of saying thank you for being a part of the community.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

The uses clause is one of those things that just tends to grow and grow. Most of the time this is in the main form, as it's from this form that all others are called. If you have a big application (including many forms), the uses clause in the in…
Introduction I have seen many questions in this Delphi topic area where queries in threads are needed or suggested. I know bumped into a similar need. This article will address some of the concepts when dealing with a multithreaded delphi database…
Are you ready to place your question in front of subject-matter experts for more timely responses? With the release of Priority Question, Premium Members, Team Accounts and Qualified Experts can now identify the emergent level of their issue, signal…
As many of you are aware about Scanpst.exe utility which is owned by Microsoft itself to repair inaccessible or damaged PST files, but the question is do you really think Scanpst.exe is capable to repair all sorts of PST related corruption issues?
Suggested Courses

850 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question