Einzelnen Beitrag anzeigen

samso

Registriert seit: 29. Mär 2009
439 Beiträge
 
#2

AW: TThreadList - So richtig?

  Alt 2. Okt 2010, 18:26
Bei der Threadliste kann ich keinen Fehler entdecken.
In der Execute-Methode würde ich noch einbauen:

Delphi-Quellcode:
if not Terminated then
  Synchronize( { GUI aktualisieren } );
Wenn die Anwendung beendet wird, besteht sonst die Gefahr, dass das Synchronize ewig auf den Hauptthread wartet, während dieser auf das Beenden des Threads wartet.
Vorschlag zum Beenden des Threads:

Delphi-Quellcode:
destructor TItemThread.Destroy;
begin
  Terminated; //Boolean setzen
  SetEvent(FTerminateEvent); // WaitForMultipleObjects aufwecken und while-Schleife verlassen
  inherited; //Führt WaitFor aus
  //Jetzt ist die Execute-Methode beendet und die internen Variablen können freigegeben werden
  FItems.Free;
  CloseHandle(FWorkEvent);
  CloseHandle(FTerminateEvent);
end;
>"Jetzt bin ich mir aber noch unsicher, was passiert, wenn AddItem und WorkItems aufgerufen wird, während der Thread noch am abarbeiten alter Items ist."

Der kritische Punkt ist das letzte Item. Der Thread glaubt die Liste sei nun leer und bearbeitet den letzten Eintrag. Jetzt wird ein neues Element hinzugefügt und der Event gesetzt (der noch gesetzt ist). Jetzt ist der Thread fertig mit dem vermeintlich letzten Element. Der Event wird zurückgesetzt - und - nichts, das neue Item wird nicht abgearbeitet. Deshalb würde ich die Events automatisch zurücksetzen lassen. Dann würde der Thread im o.a. Szenario sofort wieder einen gesetzen Event sehen und die Liste weiter abarbeiten.
Im anderen Fall - Event wurde nochmals gesetzt, während der Thread arbeitet, würde der Thread sinnlos nochmal prüfen, ob die Liste leer ist. Das ist aber leicht zu verschmerzen. Ups, da fällt mir auf, dieser Fall wird ja nicht abgefangen. Ok, das sollte man noch ändern:
Delphi-Quellcode:
            List := FItems.LockList;
            try
              bListEmpty := List.Count = 0;
              if not bListEmpty then
              begin
                Item := List[0];
                List.Delete(0);
              end;
            finally
              FItems.UnlockList;
            end;
            if not bListEmpty then
            begin
              Sleep(500); // Mit dem Item arbeiten
            end;
Und jetzt, könnte man eigentlich auch auf einen der Aufweck-Events verzichten...

Geändert von samso ( 2. Okt 2010 um 18:32 Uhr)
  Mit Zitat antworten Zitat