Natürlich habe ich eine andere Idee. Die müsste auch 'besser' sein.
Hintergrund sind 'Semaphoren'. Eigentlich ist so eine Semaphore nix anderes als ein threadsicherer Zähler mit dem man Threads steuert.
Es gibt 4 Windows-
API Prozeduren, die hier von Bedeutung sind:
CreateSemaphore erzeugt eine Semaphore mit einem definierten Anfangszustand
ReleaseSemaphore erhöht den Wert um eins,
WaitForSingleObject wartet, bis die Semaphore <>0 ist (und verringert sie dann sofort um 1) und
CloseHandle gibt das
Handle wieder an Windows zurück.
Die Idee ist folgende:
Am Anfang ist die Semaphore = 0. Wenn ein Job per AddJob in die Liste kommt, wird die Semphore um eins erhöht.
So weit, so gut. Alle Threads warten nun, bis die Semaphore <> 0 ist
und verringern die Semaphore um 1, wenn das der Fall ist. Das ist wichtig. Angenommen, zwei Threads warten auf die Semaphore. Genau 1 Job wird in die Jobliste gepackt, ergo ist die Semaphore=1. Aber: Nur ein Thread (welcher, wissen wir nicht), wird die Nachricht bekommen, das die Semaphore <>0 ist. Der andere Thread kriegt davon nix mit!
Du musst eigentlich nur Folgendes machen:
1. Die TJobList bekommt eine Property "Semaphore : THandle read fHandle".
2. TJobList.Create erzeugt eine Semaphore mit "fHandle := CreateSemaphore (nil,0,32767,nil)". Ich denke, 32767 offene Jobs sollten reichen.
3. TJobList.GetNextJob liefert '' zurück, wenn die Liste leer ist (hatte ich vergessen).
4. TJobList.Destroy gibt das fHandle mit "CloseHandle (fHandle)" wieder frei.
5. Die Execute-Methode der Threads sieht nun so aus:
Delphi-Quellcode:
Procedure TMyThread.Execute;
Begin
While Not Terminated do
If WaitForSingleObject (aJobList.Semaphore, ccMyThreadTimeout) Then Begin
aJob := aJobList.GetNextJob;
if aJob<>'' Then
DoExecuteJob (aJob);
End
End;
ccMyThreadTimeout setzt Du so auf 500 Millisecs. Du kannst auch INFINITE hinschreiben, dann warten sie wirklich *BIS* was zu tun ist, leider bekommst du dann Probleme, sie zu terminieren. Deshalb also dieses Timeout.
Prinzipiell kein Unterschied zu Deiner 'Sleep' Geschichte. WaitForSingleObjects ist aber laut Microsoft der bessere Weg, weil die CPU-Belastung minimal wird. Du kannst das Thread-timeout hochsetzen, wenn dein Programm immer läuft.
**** Nach einer Nacht drüber schlafen, bin ich heute auch etwas schlauer. Natürlich kann man die Threads endlos warten lassen. Dazu muss beim Programmende nur die Semaphore sehr hoch gezählt werden (so hoch wie es threads gibt). Schau Dir die FormDestroy-Methode einfach an...
Bei Deiner Idee, im Hauptprogramm immer mal wieder zu schauen, ob was zu tun ist (um dann die Jobliste zu füllen), kann ich Dir nicht speziell helfen, weil ich nicht weiss, was da genau los ist. Aber, prinzipiell würde ich mich an Deiner Stelle mit den Sempahoren beschäftigen.
Hier ist mein Beispiel-Projekt.