I have a thread called TMyThread and I overrode the Execute procedure like this:
procedure TMyThread.Execute;
Begin
repeat
//Some Work
Sleep(5000);
//Some Work 2;
Sleep(5000);
until FActive=False
End;
In the main form I have button called 'Destroy My Thread'. I want to destroy my thread but the problem is that my thread will be destroyed only if it finish its work. I want to destroy my thread even it has not finished its work. How do I do this?
Your thread's Execute
method must regularly check the state of the thread's Terminated
property. And if it is True
, then the thread Execute
method must exit.
So, a typical Execute
method might look like this:
procedure TMyThread.Execute;
begin
while not Terminated do
DoNextPieceOfWork
end;
It looks like your thread has its own FActive
flag that is performing the same task. The problem with that is that TThread
doesn't know about it. So you should get rid of FActive
and instead use the built in mechanism.
When you call Free
on the thread it will call Terminate
. That sets Terminated
to be True
. Then it waits for the thread method to exit. That will happen because your thread notices that Terminated
is True
and quits. And then the thread's destructor can continue and finish the job of tidying up the thread.
Looking at the code in your answer, it would be better written to make use of the existing Terminate
mechanism.
type
TMyThread = class(TThread)
private
FTerminateEvent: TEvent;
protected
procedure Execute; override;
procedure TerminatedSet; override;
public
constructor Create(ACreateSuspended: Boolean);
destructor Destroy; override;
end;
constructor TMyThread.Create(ACreateSuspended: Boolean);
begin
inherited Create(ACreateSuspended);
FTerminateEvent := TEvent.Create(nil, True, False, '');
end;
destructor TMyThread.Destroy;
begin
inherited;
FTerminateEvent.Free;
end;
procedure TMyThread.TerminatedSet;
begin
FTerminateEvent.SetEvent;
end;
procedure TMyThread.Execute;
begin
while not Terminated do
begin
// do somthing interesting!
FTerminateEvent.WaitFor(5000);
end;
end;
Now there's no need for a separate Stop
method. You can just call Free
on the thread. Then Terminate
is called. And then TerminatedSet
is called. Then the event is signaled. Then Execute
terminates. And then the thread can go away.
Having said that, I'm struggling to think of a scenario where a 5000ms timeout would be the best approach. I don't know why you are doing this, but I'd guess that you are trying to throttle the thread so that it doesn't run hot. You want to avoid a busy loop. That's admirable, but using a fixed timeout is not the way to do it. The way to do it is to wait on a synchronisation event, typically an event. Then when there is more work to be done, the event becomes signaled and your thread wakes up.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With