5

I have a code in Delphi which does the following:

procedure THilo.Execute; // (which is the thread)
begin
  inherited;
  FreeOnTerminate := True;
  while not Terminated do
  begin
    (...)
    Sleep(100);
  end;
end;

and now somewhere else, in another thread (or the GUI) we do this:

var
  Hilo2: THilo;
begin
  Hilo2 := THilo.Create(True);
  Hilo2.start;
  Hilo2 := THilo.Create(True);
  Hilo2.start;
end;

now we have executed 2 times the same thread, and they are running in parallel. What happens if we do now this?:

  Hilo2.Terminate;

will this terminate both threads or just 1, or what? also, if we would like to terminate it, could we achieve this by .Resume()?

Thanks in advance

user2308704
  • 304
  • 2
  • 10

1 Answers1

8

When you create the second thread you are overwriting the local variable Hilo2 with a pointer to the second object - the first object's pointer is lost and you no longer have any reference to it (or way to control it). This will result in a memory leak if the thread does not terminate itself and, no, calling terminate will not stop both threads, only the one last created with that variable as reference. Also, there is no need to call inherited in the Execute method of a TThread - there is nothing to inherit (TThread's execute method is abstract, it doesn't do anything).

J...
  • 30,968
  • 6
  • 66
  • 143
  • Thanks J, I had in my program this and couldn't Terminate the threads so it would be fixed with just an array of a TThread, right? like ` Hilo[i] := THilo.Create(True); Hilo[i].start;` – user2308704 May 21 '13 at 23:28
  • 1
    Oh - another skilled Delphi multithread developer. That makes at least two of us :) – Martin James May 21 '13 at 23:48
  • 3
    Also, since `FreeOnTerminate=True` is being used, if the thread terminates prematurely (uncaught exception, etc), then calling `Terminate()` may fail (or worse, corrupt memory) if the thread is already gone. `FreeOnTerminate=True` should only be used for create-and-forget threads. As soon as you have to externally touch a thread for **any** reason (suspend/resume, terminate/waitfor, updates/accesses to members, etc), don't use `FreeOnTerminate=True`! – Remy Lebeau May 21 '13 at 23:51
  • @user2308704 an array would work - however you do it you need to keep a reference to each thread you create. – J... May 21 '13 at 23:52
  • 4
    Another gotcha - if you are going to use `FreeOnTerminate=True`, set it in the constructor instead (or at least before `Resume/Start()` is called when `ACreateSuspended=True`). This is because a few years ago, `TThread` was updated to not call `Execute()` at all if `Terminate()` is called before the thread actually begins running. If `Execute()` sets `FreeOnTerminate=True`, you risk a memory leak. – Remy Lebeau May 21 '13 at 23:59
  • 7
    @MartinJames Stop being so arrogant. – David Heffernan May 22 '13 at 04:40