Чтобы цикл ожидания потоков не напрягал процессор почём зря, нужно в этом цикле сделать небольшую задержку:
Код:
repeat
Sleep(100); // Теоретически достаточно даже Sleep(0)
enp := True;
for it := 0 to itc - 1 do
enp := enp and ther[it].Finished;
until enp;
Кроме того вместо самопального цикла ожидания можно использовать стандартную
WaitForMultipleObjects которая умеет ожидать до 64 объектов синхронизации одновременно.
И да, при "FreeOnTerminate:=True" неправомерно выполнять обращения к объекту этого потока из другого потока, так как объект к этому времени уже может быть разрушен (вследствие завершения выполнения потока). Если необходимо обращаться к объекту потока из другого потока нужно делать "FreeOnTerminate:=False", но тогда и самостоятельно разрушать объекты потоков (или возложить эту миссию на объект класса TObjectList из модуля Contnrs).
Если же делать "FreeOnTerminate:=True", то так как к такому объекту потока, нельзя обращаться из другого потока - поток должен сам как-то оповестить о своём завершении. Например можно объявить глобальную переменную-счётчик потоков. При создании нового потока увеличивать эту переменную, а каждый поток перед своим завершением должен уменьшать эту переменную (обязательно через Synchronize или InterlockedDecrement), тогда в цикле достаточно просто проверять не достигло ли значение этой переменной нуля:
Код:
var
NumThr: Integer = 0; // Это будет счётчик запущенных потоков
.....
begin
.....
for it := 1 to itc do
begin
ther[it-1] := Rasch.Create(True);
Inc(NumThr); // Увеличиваем количество созданных потоков на единицу
ther[it-1].FreeOnTerminate := True; // Авторазрушаемый объект потока
.....
ther[it-1].Resume;
end;
while NumThr > 0 do Sleep(100); // Ожидаем завершения всех потоков
.....
end;
.....
.....
procedure Rasch.Execute;
begin
proc(kss, ke);
InterlockedDecrement(NumThr); // Перед завершением потока уменьшаем количество
// запущенных потоков, а объект потока сам разрушится
// благодаря FreeOnTerminate := True
end;