tags:

views:

120

answers:

4

Dear All,

In delphi, a method in TThread is terminate. It seems a subthread can not kill another thread by calling terminate or free. For example A(main form), B (a thread unit), C (another form).

B is sending data to main form and C (by calling syncronize), we tried to terminate B within C while B is executing by calling B.terminate. But this method does not work and B is still working until it ends in execute method.

Please help. Thank you in advance.

+3  A: 

Terminate does not kill a thread; it sets the Terminated property to inform the thread that it needs to terminate. It's the thread's responsibility to watch for Terminated and shut itself down gracefully.

Mason Wheeler
A: 

Terminate and Free do not kill a thread at all. You should never call Free on a running TThread instance.

Normally you should add some code that checks if Terminated has been set to True to your Execute method.

If you really have to do it use the Windows.TerminateThread function. You can obtain the thread id from the TThread.ThreadID instance member. This is usally a very bad idea though.

Jens Mühlenhoff
Calling Free on a running thread is perfectly valid. In fact, it will call Terminate and then *wait* for the thread to finish before freeing the instance.
Allen Bauer
A: 

All the Terminate method does is it sets the Terminated property to true. So you have to manually keep checking that property and then exit the thread method when it is set to true.

Timo
+9  A: 

You have to check for Terminate in the thread for this to work. For instance:

procedure TMyThread.Execute;
begin
  while not Terminated do begin
    //Here you do a chunk of your work.
    //It's important to have chunks small enough so that "while not Terminated"
    //gets checked often enough.
  end;
  //Here you finalize everything before thread terminates
end;

With this, you can call

MyThread.Terminate;

And it'll terminate as soon as it finishes processing another chunk of work. This is called "graceful thread termination" because the thread itself is given a chance to finish any work and prepare for termination.

There is another method, called 'forced termination'. You can call:

TerminateThread(MyThread.ThreadId);

When you do this, Windows forcefully stops any activity in the thread. This does not require checking for "Terminated" in the thread, but potentially can be extremely dangerous, because you're killing thread in the middle of operation. Your application might crash after that.

That's why you never use TerminateThread until you're absolutely sure you have all the possible consequences figured out. Currently you don't, so use the first method.

himself
Thank you Timo. Clear answer and examples.
And thank you himself. a very good example.
It's not only the application may crash, but also resources used by the thead won't be deallocated. TerminateThread() is an "extrema ratio" call.
ldsandon
@himself: you could have the thread call "Abort" inside the thread context when it finds Terminated set to True. "Abort" will raise a silent exception. Sometimes this way you get easier logic than having a big "while not Terminated" loop.
Jeroen Pluimers
Dear himself: Just test your code but the thread can not gracefully exit. While not terminated do begin UNTIL the thread Execute function ends. Why? Instead, Terminatethread function does good job though it is not recommended by most experts.
@user482742: Edit your question and add the code so we can tell you what's the problem.
himself