Delphi - Custom thread not being created

403 Views Asked by At

i'm having a bit of a problem here. I have a custom class that inherits TPersistent class, inside(private section) this custom class, i have a custom made TThread with overriden Execute method which fires every (1000 ms). Everything works great, until i move my 2 custom classes to a new Unit...

type
  TMyThread= class(TThread)
  protected
   procedure Execute; override;
  end;

  TMyClass = class(TPersistent)
  private
   T: TMyThread;
  protected
   constructor Create;
  public
   destructor Destroy; override;
  end;


implementation

procedure TMyThread.Execute;
begin
 while not Self.Terminated do begin
  Sleep(1000);
  MessageBox(0, 'test', nil, MB_OK)
 end;
end;

constructor TMyClass.Create;
begin
 inherited Create;
 t := TMyThread.Create(False);
end;

destructor TMyClass.Destroy;
begin
 t.Terminate;
 t.WaitFor;
 FreeAndNil(t);
 inherited Destroy;
end;

The above code works great in the main project unit, but when i move it to a new unit, the thread code no longer works, i get an AV, when i try to free a TMyClass object. I think the thread is not being constructed at all, and that's why i get an AV when i try to free it... but why? it shouldn't matter in which Unit the code is...

Unit1:

unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls, unit2;

type
  TForm1 = class(TForm)
    Button1: TButton;
    Button2: TButton;
    procedure Button2Click(Sender: TObject);
    procedure Button1Click(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form1: TForm1;
  p: TMyClass;

implementation

{$R *.dfm}

procedure TForm1.Button2Click(Sender: TObject);
begin
 p.Free; //Getting an AV
end;

procedure TForm1.Button1Click(Sender: TObject);
begin
 p := TMyClass.Create;
end;

end.

Unit2:

unit Unit2;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs;

type
  TMyThread = class(TThread)
  protected
   procedure Execute; override;
  end;

  TMyClass = class(TPersistent)
  private
   T: TMyThread;
  protected
   constructor Create;
  public
   destructor Destroy; override;
  end;


implementation

procedure TMyThread.Execute;
begin
 while not Self.Terminated do begin
  Sleep(1000);
  MessageBox(0, 'test', nil, MB_OK)
 end;
end;

constructor TMyClass.Create;
begin
 inherited Create;
 t := TMyThread.Create(False);
end;

destructor TMyClass.Destroy;
begin
 t.Terminate;
 t.WaitFor;
 FreeAndNil(t);
 inherited Destroy;
end;

end.
1

There are 1 best solutions below

1
On BEST ANSWER

The constructor TMyClass.Create is declared protected. That means it is not visible from another unit. Hence TMyClass.Create is not executed and instead you are calling TObject.Create. In turn that means that the thread is never created and you encounter a runtime error when the destructor runs because T is nil.

Declare the constructor with public visibility.