Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to free a thread in delphi

I have multithreaded application as I ask here. I want to terminate the thread, and start a new one when following method is called.

procedure TFRABData.RefreshDataset;
var
  GridUpdater: TGridUpdater;
begin
  if Assigned(updaterThread) and (updaterThread <> nil) then
  begin
    updaterThread.Terminate;
  end;
  GridUpdater := TGridUpdater.Create(True);
  GridUpdater.OwnerForm := Self;
  updaterThread := GridUpdater;
  GridUpdater.FreeOnTerminate := False;
  GridUpdater.Start;
  CodeSite.Send('RefreshDataset executed');
end

but, when FreeOnTerminate set to True, I get Access Violation, but when FreeOnTerminate set to False, I get memory leak. How to free the thread?

like image 295
Niyoko Avatar asked Sep 25 '12 06:09

Niyoko


3 Answers

You need to call Terminate(), WaitFor() and Free() all together, eg:

procedure TFRABData.RefreshDataset; 
var 
  GridUpdater: TGridUpdater; 
begin 
  if Assigned(updaterThread) then 
  begin 
    updaterThread.Terminate; 
    updaterThread.WaitFor; 
    FreeAndNil(updaterThread); 
  end; 
  GridUpdater := TGridUpdater.Create(True); 
  GridUpdater.OwnerForm := Self; 
  GridUpdater.Start; 
  updaterThread := GridUpdater; 
  CodeSite.Send('RefreshDataset executed'); 
end;
like image 106
Remy Lebeau Avatar answered Oct 24 '22 02:10

Remy Lebeau


And in addition to RRUZ's answer, to let it work with FreeOnTerminate = False:

Terminate just sets the flag, it does nothing more.

Change

  if Assigned(updaterThread) and (updaterThread <> nil) then 
  begin 
    updaterThread.Terminate; 
  end; 

to

  if Assigned(updaterThread) then 
  begin 
    updaterThread.Free; 
  end; 

Free will call Terminate and WaitFor subsequently to eliminate your memory leak.

like image 35
NGLN Avatar answered Oct 24 '22 02:10

NGLN


  1. avoid the need of start a suspended thread
  2. modify your TThread constructor to receive the OwnerForm parameter
  3. set the FreeOnTerminate value in the constructor of your thread.
  4. Start the TThread in a not suspended state.

something like so.

  TGridUpdater = class(TThread)
  private
    FOwnerForm: TForm;
  public
    constructor Create(OwnerForm : TForm); overload;
    destructor Destroy; override;
    procedure Execute; override;
  end;

constructor TGridUpdater.Create(OwnerForm: TForm);
begin
  inherited Create(False);
  FreeOnTerminate := True;
  FOwnerForm:=OwnerForm;
end;

destructor TGridUpdater.Destroy;
begin

  inherited;
end;

procedure TGridUpdater.Execute;
begin
  //your code goes here

end;

Now you can create your Tthread on this way

GridUpdater:=TGridUpdater.Create(Self); //Just set it and forget it
like image 6
RRUZ Avatar answered Oct 24 '22 02:10

RRUZ