Solved

Cancel a TThread in middle of execution!

Posted on 2004-05-01
12
758 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
 
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
Enabling OSINT in Activity Based Intelligence

Activity based intelligence (ABI) requires access to all available sources of data. Recorded Future allows analysts to observe structured data on the open, deep, and dark web.

 

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

What Should I Do With This Threat Intelligence?

Are you wondering if you actually need threat intelligence? The answer is yes. We explain the basics for creating useful threat intelligence.

Join & Write a Comment

Objective: - This article will help user in how to convert their numeric value become words. How to use 1. You can copy this code in your Unit as function 2. than you can perform your function by type this code The Code   (CODE) The Im…
Have you ever had your Delphi form/application just hanging while waiting for data to load? This is the article to read if you want to learn some things about adding threads for data loading in the background. First, I'll setup a general applica…
Here's a very brief overview of the methods PRTG Network Monitor (https://www.paessler.com/prtg) offers for monitoring bandwidth, to help you decide which methods you´d like to investigate in more detail.  The methods are covered in more detail in o…
Polish reports in Access so they look terrific. Take yourself to another level. Equations, Back Color, Alternate Back Color. Write easy VBA Code. Tighten space to use less pages. Launch report from a menu, considering criteria only when it is filled…

747 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

16 Experts available now in Live!

Get 1:1 Help Now