@Slawek
You cannot combine your "FIN" method with MyThread.Terminate it can lead to exception. When you set Fin to true, the thread's Execute method is exited and the thread terminated. At the time you call MyThread.Terminate, the thread is long gone.
A better solution is to check the Terminated flag before you do a long operation inside the thread, if Terminated is true, break the for cycle and exit the thread. On the other hand if the thread has finished all tasks, and terminated is still false, put the thread to idle and wait until MyThread.Terminated is called from the main thread. Something like this:
procedure TMyThread.Execute;
var
I: Integer;
begin
//...
for I := 1 to 9 do
begin
if Terminated then
Break; //abort
newStatus := 'Task no ' + I.ToString;
Sleep(500);
if newStatus <> fStatusText then
begin
fStatusText := newStatus;
if not Terminated then //only syncrhonize if terminated is false
Synchronize(@Showstatus);
end;
end;
while (not Terminated) do
Sleep(100); //thread is idle, wait until MyThread.Terminate is called
end;
The idea is to create, terminate and free the worker thread(s) from the main thread. When you wish to free a particular thread:
MyThread.Terminate; //this will set the Terminated flag to true
MyThread.WaitFor;
MyThread.Free;
WaitFor is critical. Not calling WaitFor can lead to deadlock(worker thread waits for the main thread, main thread waits for the worker thread...).
PS: If you have a list of mythreads, just before a particular thread goes to idle, set a public boolean variable Fin to true. From time to time loop through the list, check if a thread is idle(fin := true) then terminate/free the thread and remove it from the list.