My TThread crashes ? but don't know why

my thread is for delayed file save

 TLazySave = class(TThread)
  protected
    FList: TKeyList;
    Procedure Execute;
  public
    constructor Create(List: TKeyList); reintroduce;
  end;

and calling the Create reintroduce; so it crashes at the inherited in the create

constructor TLazySave.Create(List: TKeyList);
begin
  inherited Create(False); // False means it will start right away
  FreeOnTerminate := True; // Free memory when finished
  FList := List;
end;

procedure TLazySave.Execute;
begin
  Sleep(2000);
  FList.DoLazySaveData;
end;

I’m doing a Terminate and nil process and you see a 2 second wait
So my code looks to see if LazySave = nil before recreating a new object?
So evert time the object is accessed the LazySave thread is restarted to reintroduce the full Sleep(2000) again.

trying to keep it simple and that may add processing but this way saves RAM space when not used

Should I start it once in TKeyList and use Terminate and Terminated or what should I be doings

If the thread is FreeOnTerminate := True and you have a variable pointing to an instance of TLazySave (eg: LazySave := TLazySave.Create( ... ) ), then your LazySave variable will become a bad pointer. And if you try to use that, there is a good chance that you will get an Access Violation exception. Just because the thread terminates itself, Delphi does/will not update any pointers that were point to it. :slight_smile:

If you gave us the error message, we might be able to make a better guess at what is happening, or show us were the error is happening (line) but until more information is provided, it is all guess work on our part. :frowning:

1 Like

You don’t want reintroduce.

Look at this code from StackOverflow (multithreading - Working with Delphi TThread - Stack Overflow)

TMyThread= class(TThread)
  private
    Fsource, FDest: String;
  public
    constructor Create(Const Source, Dest: string);
    destructor  Destroy;   override;
    procedure   Execute(); override;
end;

{ TMyThread }

constructor TMyThread.Create(const Source, Dest: string);
begin
  inherited Create;
  Fsource := Source;
  FDest   := Dest;
  Self.FreeOnTerminate := True;
end;

destructor TMyThread.Destroy;
begin
  inherited;
end;

procedure TMyThread.Execute;
begin
  try
    TDirectory.Copy(Fsource, FDest);
  except on E: Exception do
  end;
end;

procedure TForm1.Button1Click(Sender: TObject);
begin
  var MT := TMyThread.Create('Source', 'Destination');
end;

may be I need to show you this code

when a thread enters the object

procedure TKeyList.StartLazySaveKeyData;
begin   //ok
  While FLazySaveOn do
   begin
     FExtThread := LBWaiting;
     Sleep(100);
   end;
   FExtThread := LBRuning;
   If FLazySave <> nil then
    begin
     FLazySave.DoTerminate;
     FLazySave := nil;
    end;
end;

when a thread exits the object

procedure TKeyList.FinishLazySaveKeyData(Key: TKey);
begin  //  ok
  FKeysToSave.Add(Key);
  Key.FDataChanged := True;
  If FLazySave = nil then FLazySave.Create(Self);
  FExtThread := LBGone;
end;

the code my lazy slave excites

procedure TKeyList.DoLazySaveKeyData;
var Key: TKey;
begin  // ok
  FLazySaveOn := True;
  While FExtThread = LBRuning do Sleep(100);
  While (FKeysToSave.Count > 0) and (FExtThread <> LBWaiting) do
    begin
     SaveKeyData(TKey(FKeysToSave.Items[0]));
     FKeysToSave.Delete(0);
    end;
  While (FKeysToClearStream.Count > 0) and (FExtThread <> LBWaiting) do
    Begin
     TKey(FKeysToClearStream.Items[0]).FStream.Size := 0;
     FKeysToClearStream.Delete(0);
    End;
  FLazySave.Terminate;
end;

I’m thinking FLazySaveOn could be removed replaced with FLazySave = nil

[Paul_McGee]

why is their no reintroduce on your create

I see I forgot the

 Procedure Execute;   // no override on my code? 

Put the override in and no better but left it in

constructor TLazySave.Create(List: TKeyList);
begin
  inherited Create(False); 

can this inherited Create(False); be my error ???
am I not allowed the false ?

If I arranged TLazySave to be created in TKeyList.create
FreeOnTerminate := False;
and Destroyed in TKeyList.Destroy;
and use
If not LazySave.Terminated then LazySave.Terminate;
will that work?

or is it

  protected
    Procedure Execute;

should be

  public
    Procedure Execute;

I changed my code around

constructor TLazySave.Create(List: TKeyList);
begin
  FList := List;
  inherited Create(False); // False means it will start right away
  FreeOnTerminate := True; // Free memory when finished
end;

The error was at FList := List;
And the error code is 000000005 access violation
And FList := List; is listed in the headder where it should be so we have something wrong about entering into the constructor create !!!
its nothing about what is wrong in the code in the constructor create its that its not allocated for access? why?

What’s wrong with a TTimer with a 2 sec interval, flip Enabled, it executes?

TTimer is a component
its easy to use but more complicated used in a DLL
error code is 000000005 access violation why is the thread object not allocating stack space for its self???
The same access violation is noted by the compiler with the inherited line too
its registered as a standard object within a working object?
do i need a custom object between TThread ?

I don’t know if this helps
the error does not have to adjust data - its that its in the create passing the ‘begin’ and that makes the error

my TLazySave is registered in my TKeylist object as FLazySave: TLazySave;
my TKeylist object is very big with a lot in it and going well

I know a thread is not to be run during create of objects or when an app is starting up
But the TLazySave header in under implementation and not above implementation
can I do that?

I found the error
fixed it was a typo error