1

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.
4
  • Why are you displaying a MessageBox in a thread? Commented May 23, 2015 at 6:58
  • It was for testing purpose only, nothing more, wanted to save some time. To test, if the thread fired. Commented May 23, 2015 at 6:59
  • If you use the debugger, you will notice that no code is generated for the TMyClass.Create constructor. (No blue dots). This will give you a good hint what is going on. Commented May 23, 2015 at 7:25
  • Now i noticed, i should use the debugger more often, Thank you for the advice! Commented May 23, 2015 at 7:35

1 Answer 1

3

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.

Sign up to request clarification or add additional context in comments.

1 Comment

It worked, silly me... i'm kinda new to OOP, i should read some extra info on those Protected, Public, Published sections Thank you soo much, have a good day kind sir!

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.