Falls Du D6 benutzt, vergiss Synchronize, das klappt nicht.
Weiterhin solltest Du den Datenaustausch mit Threads irgendwie mit CriticalSections sichern. Anstatt direkt das Feld 'FTodo' zu setzen (ist doch nicht
OOP, Mensch), schreib Dir eine Get- und eine Set-Methode im Thread. Den Zugriff auf das Feld fToDo kapselst du mit einer Critical Section.
So ist sichergestellt, das sich lese- und schreiboperationen nicht in die Quere kommen.
Obwohl das bei Dir eigentlich nicht passieren dürfte, da de NewJob Methode im Kontext des Hauptthreads ausgeführt wird...
Wenn ich mir das recht überlege, ist das aber nicht sonderlich cool, wie Du das machst. Ich würde die Todo-Liste erstmal als TThreadList implementieren, weil eben viele Threads darauf zugreifen. Das sollten sie auch gleichzeitig können. Ergo:
Delphi-Quellcode:
Type
TJobList = Class
Private
fList : TThreadList;
Public
Function GetNextJob : TJob;
Procedure AddJob (aJob : TJob);
End;
Function TJobList.GetNextJob : TJob;
Var
l :TList;
Begin
l := fList.LockList;
Try
if l.Count = 0 Then
Result := Nil
else begin
Result := l[l.count - 1];
l.delete (l.count - 1);
End;
Finally
fList.unlockList;
End;
End;
Procedure TJobList.AddJob (aJob : TJob);
Var
l :TList;
Begin
l := fList.LockList;
Try
l.Add (aJob);
Finally
fList.unlockList;
End;
End;
Nun kannst Du die Jobliste füllen (auch während die Threads ackern). Jeder Thread holt sich dann, wenn er fertig ist, den nächsten Job per GetNextJob und macht weiter. Liefert GetNextJob den Wert nil, macht der Thread eben nichts. Das ist ein kleines Problem, weil es nicht so leicht ist, einem Thread zu sagen, er soll nichts machen (also, auch keine CPU verbraten). Man muss ein Synchronisationsobjekt nehmen, ich würde es mit einer Semaphore versuchen. Jedesmal, wenn ein Job per AddJob in die Joblistee reingepackt wird, wird die Sempahore um eins erhöht.
Jeder Thread wartet, bis die Semaphore<>0 ist und holt sich einen Job aus der Liste. Nicht ausprobiert, sollte aber klappen.