How can I properly stop a thread when an application is closing?
I do this:
procedure TForm1.FormCloseQuery(Sender: TObject; var CanClose: Boolean);
begin
if not Thread1.Finished
then
begin
Thread1.Terminate;
Thread1.WaitFor();
end;
end;
But on Thread1.WaitFor I have an error: "Thread Error: The handle is invalid (6)." If I do WaitForSingleObject(Thread1.Handle,infinite) instead of WaitFor all is ok.
Why if I use Thread.freeonterminate := false then WaitFor works good? Explain me please what I do wrong. As I understand I need to use "if Assigned" instead of "if not Thread1.Finished", right?
When you set FreeOnTerminate = True
, the thread object automatically frees itself when it terminates. So, after it terminates, any further calls on that object are invalid. As soon as you call Terminate
, you have to assume that the object no longer exists.
If you need to do further operations on a thread after starting it, then don't set FreeOnTerminate
. Instead, free it manually after you're really finished using it.
The only time you would use Assigned
is if you're expecting the Thread1
variable to be nil
. Do you ever assign Thread1 := nil
? If not, then you shouldn't expect it to have that value. As you should know, variables don't suddenly change their values when you call methods on them. But if you've set FreeOnTerminate
, then it's incorrect to check the Finished
property, too, because it might have already finished and freed itself.