Correct thread destroy
Asked Answered
F

3

5

Hello At my form I create TFrame at runtime. At this frame I create background thread with executes commands in endless loop. But when I destroy this frame I should destroy this thread. I try

thread.Suspend;
thread.Terminate;
FreeAndNil(thread);

but get AV and ThreadError. How should i destroy thread?

Fulbright answered 24/9, 2010 at 15:45 Comment(3)
possible duplicate of Free a TThread either automatically or manuallyDebate
Don't suspend the thread. The terminate method just set the Terminated property to true, and your Execute method is responsible to terminate the thread. If it is suspended, it will not get a chance to terminate.Seventy
Another problem with the code above, is that it likely frees the thread before it has a change to terminate the normal way.Bushhammer
C
13

You must make sure that the thread exits its Execute method to terminate it properly.

Code could be something like this:

procedure TThread.Execute;
begin
  while not Self.Terminated do
  begin
    //do something
  end;
end;

Call this when You want to destroy thread:

thread.Terminate;
thread.WaitFor;
FreeAndNil(thread);
Congdon answered 24/9, 2010 at 15:56 Comment(1)
It's not necessary to call Terminate and WaitFor from the outside, as the thread destructor will do it itself. It may be necessary though to call it from overwritten destructors, before any fields are freed, to make sure these are no longer used from the thread.Cognoscenti
B
4

It is sufficient to do thread.Terminate. But you will probably want to set thread.FreeOnTerminate := true when it is created.

Of course, in the tight loop of your thread (that is, in Execute), you need to check if the thread has been requested to terminate (check the Terminated property). If you find that the thread has been requested to terminate, simply break from the loop and exit from Execute.

Bushhammer answered 24/9, 2010 at 15:50 Comment(2)
thread.Terminate only sets FTerminated property to True. It doesn't destroy thread.Congdon
I know. But every thread must check for that in its Execute method. I assume the OP is doing this.Bushhammer
D
4

You should never call suspend on a tthread its not safe to do so and resume should only be used to start a thread that was created suspended.

In Delphi 2010 the suspend and resume where depreciated and the method start was introduced to reinforce this.

For a more complete explanation see this thread at Codegears forums.

having said that there are 2 ways I will terminate and free a tthread.

1: I Set FreeOnTerminate when the thread is created so I just call.

Thread.Terminate;

2: Free the thread explicitly, as I need to read a result from a public property before the thread is freed and after it has terminated.

Thread.Terminate;
Thread.WaitFor;
//Do somthing like read a public property from thread object
if Thread <> nil then FreeAndNil(Thread);

In the main execute loop it may be a good idea to put some exception handling in. Or you may be left wondering why the thread appears to terminate its self. This may be causing the AV if the thread is set to FreeOnTerminate and it has already been freed when you try to free it.

procedure TThread.Execute;
begin
  while not Terminated do
  begin
    try
      //do something
    except
      on E:Exception do
       //handle the exception
    end;
  end;
end; 
Dudeen answered 26/9, 2010 at 2:26 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.