Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why do I get "The handle is invalid" when waiting for a thread I've told to terminate?

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?

like image 544
maxfax Avatar asked Jun 11 '11 02:06

maxfax


1 Answers

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.

like image 70
Rob Kennedy Avatar answered Sep 21 '22 15:09

Rob Kennedy