Reputation: 33
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.
Upvotes: 1
Views: 408
Reputation: 612934
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.
Upvotes: 3