The problem is diferent.
It is in your thread.
You created thread and set it to terminate on finish...
...and you do not have loop inside. The main thread procedure (Execute) went to the finish and thread commit the suicide

The code in the thread should look like the following:
Код:
procedure TTestThread.Execute;
begin
FreeOnTerminate:=true;
While not Terminated do
begin
form1.Button4.Click;
end;
end;
And, off cause, it is better to move the actual code from main form to the thread and build the event-driven or synchronized callback interface to update indicators on the main form. For example, you can leave the thread to run constantly and pass the tasks from main form. The other option is to build the thread pool and task queue. In this case mainj form put tasks to the queue and each thread (use critical section to sync between the threads) will grab tasks from this queue. As soon as no tasks in the queue, each thread inform the pool (to remove the pointer from it) and die. I did this architecture in one of my application and it works fine.