Solved

Cancel a TThread in middle of execution!

Posted on 2004-05-01
12
760 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 500 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
Live: Real-Time Solutions, Start Here

Receive instant 1:1 support from technology experts, using our real-time conversation and whiteboard interface. Your first 5 minutes are always free.

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

Gigs: Get Your Project Delivered by an Expert

Select from freelancers specializing in everything from database administration to programming, who have proven themselves as experts in their field. Hire the best, collaborate easily, pay securely and get projects done right.

Question has a verified solution.

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

Suggested Solutions

Hello everybody This Article will show you how to validate number with TEdit control, What's the TEdit control? TEdit is a standard Windows edit control on a form, it allows to user to write, read and copy/paste single line of text. Usua…
In my programming career I have only very rarely run into situations where operator overloading would be of any use in my work.  Normally those situations involved math with either overly large numbers (hundreds of thousands of digits or accuracy re…
This Micro Tutorial will give you a basic overview how to record your screen with Microsoft Expression Encoder. This program is still free and open for the public to download. This will be demonstrated using Microsoft Expression Encoder 4.
Along with being a a promotional video for my three-day Annielytics Dashboard Seminor, this Micro Tutorial is an intro to Google Analytics API data.

813 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

Need Help in Real-Time?

Connect with top rated Experts

10 Experts available now in Live!

Get 1:1 Help Now