Ja jak potrzebuję wątków to idę po prostu po najmniejszel lini oporu i robię to tak.
Najpierw odpalam wątek ,który robi za kierownika (uruchamia pracowników i czeka aż skończą pracę). Celowo używam najpierw wątka kierownika aby nie blokować głównego watku aplikacji.
type
TSupervisorThread = class(TThread)
private
{ Private declarations }
CopiedProgress:integer;
protected
procedure Execute; override;
end;
type
TWorkerThread = class(TThread)
private
{ Private declarations }
ThreadIndex:integer;
protected
procedure Execute; override;
end;
var Progress:integer;
procedure TSupervisorThread.Execute;
var x:integer;
WaitStatus,Threads:cardinal;
WorkerThreadArray:array of TWorkerThread;
WorkerThreadHandleArray:array of THandle;
begin
Threads:=16; //np. 16 wątków
SetLength(WorkerThreadArray,Threads);
SetLength(WorkerThreadHandleArray,Threads);
for x:=0 to Threads-1 do
begin
WorkerThreadArray[x]:=TWorkerThread.Create(True);
WorkerThreadHandleArray[x]:=WorkerThreadArray[x].Handle;
WorkerThreadArray[x].FreeOnTerminate:=false;
WorkerThreadArray[x].Priority:=tpNormal;
WorkerThreadArray[x].ThreadIndex:=x;
WorkerThreadArray[x].Resume;
end;
repeat
WaitStatus:=WaitForMultipleObjects(Threads, @WorkerThreadHandleArray[0], True, 100);
Synchronize(GetProgress);
if Terminated=true then for x:=0 to Threads-1 do
begin
WorkerThreadArray[x].Terminate;
if WorkerThreadArray[x].Suspended=true then WorkerThreadArray[x].Resume;
end;
until WaitStatus<>WAIT_TIMEOUT;
for x:=0 to Threads-1 do if Assigned(WorkerThreadArray[x])=true then FreeAndNil(WorkerThreadArray[x]);
end;
procedure TSupervisorThread.GetProgress;
begin
CopiedProgress:=Progress; // albo pokazać gdzieś w GUI
end;
procedure TWorkerThread.Execute;
begin
{jakaś praca tutaj}
Synchronize(UpdateProgress)
end;
procedure TWorkerThread.UpdateProgress;
begin
Inc(Progress);
end;
po linii najmniejszego oporu
. :P