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.
The constructor
TMyClass.Createis declared protected. That means it is not visible from another unit. HenceTMyClass.Createis not executed and instead you are callingTObject.Create. In turn that means that the thread is never created and you encounter a runtime error when the destructor runs becauseTisnil.Declare the constructor with
publicvisibility.