Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Object-Pascal / Delphi-Language (https://www.delphipraxis.net/32-object-pascal-delphi-language/)
-   -   Delphi FreeOnTerminate -> Terminated bleibt stets false (https://www.delphipraxis.net/90373-freeonterminate-terminated-bleibt-stets-false.html)

hirnstroem 16. Apr 2007 12:50


FreeOnTerminate -> Terminated bleibt stets false
 
'loha Folks,

auf einem Formular befindet sich ein Timer, welcher bei jedem Interval überprüft ob ein bestimmter Thread noch lebt oder nicht. Je nach Thread-Status führt der Timer dann bestimmte Methoden aus. Nun ist es so, dass ich dem Thread beim kreieren mitteile dass er sich selber freigeben soll, wenn er seine Arbeit vollendet hat (FreeOnTerminate := True). Leider scheint der Thread sich aber niemals terminieren zu wollen, obwohl er zweifelsfrei bereits allen Code abgearbeitet hat (wenn ich am Ende des Threads z.B. noch ein Beep hinsetzte, so ertönt dieses stets). Im Timer, in welchem überprüft wird ob der Thread noch lebt, heisst es aber stets, dass Terminated = False sei, der Thread also noch nicht wirklich terminiert ist. Nachfolgend noch ein bisschen Code, wobei ich dazu sagen muss, dass auch wenn alles bis auf die erste Zeile auskommentiert ist, der Thread schon nicht mehr terminiert. Weiss jemand Rat?

Delphi-Quellcode:
procedure TReadNewKeyThread.Execute;
var
  ReceivedCode, SmallestCode, NumberCode: String;
begin
  ReceivedCode := DI.ReadNewKey(FUserSession.DataSet.FieldByName('Address').Value);
  if ReceivedCode <> '-1' then
  begin
    SmallestCode := IntToHex(DI.FindSmallestCode(HexToInt(ReceivedCode)), 16);
    NumberCode := DI.ConvertCodeToUniqueNumber(SmallestCode);
    IWServerController.SearchKeyCode(SmallestCode);
    if IWServerController.ADODataSet_Key.RecordCount <> 0 then
    begin
      if FUserSession.UserLanguage = 'deCH' then FUserSession.ShowMessage := 'Fehler: Der Schlüssel mit der Nummer ' + NumberCode + 'wurde bereits in der Datenbank erfasst'
      else if FUserSession.UserLanguage = 'enUS' then FUserSession.ShowMessage := 'Failure: A key with the number ' + NumberCode + ' already exists in the database';
      ReadKeyVisible := False;
    end
    else
    begin
      KeyCode := SmallestCode;
      KeyNumber := NumberCode;
      ReadKeyString := KeyNumber;
      if KeyNumber <> '00000000000000' then
      begin
        ReadKeyEnabled := True;
        ReadKeyVisible := True;
      end;
    end;
  end
  else
  begin
    ReadKeyString := '';
    ReadKeyEnabled := False;
    ReadKeyVisible := False;
  end;
end;
Grüsse
hirnstroem

Robert Marquardt 16. Apr 2007 12:58

Re: FreeOnTerminate -> Terminated bleibt stets false
 
Wenn du FreeOnTerminate gesetzt hast, dann zerstoert sich das Thread-Objekt selbst. Irgendwann greifst du daher auf einen bereits freigegebenen Speicherbereich zu. Es kann durchaus sein das zur Optimierung Terminated nicht gesetzt wird. Wozu auch, da doch das Objekt freigegeben wird.
Wozu eigentlich der Unsinn mit einem Timer? Setz doch den OnTerminate-Event des Threads geeignet.

Luckie 16. Apr 2007 13:02

Re: FreeOnTerminate -> Terminated bleibt stets false
 
Nun, überlegen wir mal. Dein Timer fragt ständig den Wert von Terminated ab. Und bekommt auch True zurück so lange der Thread lebt. Der Thread beendet seine Aufgabe und gibt sich selber frei. Welchen Wert hat jetzt wohl die Eigenschaft Terminated von einem Thread-Objekt, welches nicht mehr existiert? Ich würde sagen, du hast noch Glück, dass die keine AccessViolation bekommst.

Du hast drei Möglichkeiten, um benachrichtigt zu werden, ob der Thread mit seiner Aufgabe fertig ist:
  1. Du nutzt die Methode WaitFor der TThread-Klasse.
  2. Der Thread löst ein Ereignis aus.
  3. Der Thread schickt an dein Fenster eine Nachricht mit MSDN-Library durchsuchenSendMessage.

hirnstroem 16. Apr 2007 13:08

Re: FreeOnTerminate -> Terminated bleibt stets false
 
Zitat:

Zitat von Robert Marquardt
Wozu eigentlich der Unsinn mit einem Timer?

Unsinn? Ich finde das eine schöne Sache. Der Timer wird dazu benutzt um zu schauen wie es um den Thread steht und aktualisiert zugleich eine Fortschrittsanzeige (auf einem Webinterface...asynchron). Aber mit dem Ereignis gefällt mir das noch besser.

Danke dir, Grüsse
hirnstroem

Robert Marquardt 16. Apr 2007 13:49

Re: FreeOnTerminate -> Terminated bleibt stets false
 
Auch eine Fortschrittsanzeige kann man sich im Thread implementieren. Man leitet ja sowieso TThread ab, da kann man ihm auch noch einen Fortschrittsevent dazubauen. Es aendert sich zwar nun die Berechnungsart komplett, aber das schadet nichts wenn man es richtig macht. Der Timer weiss wieviel Zeit vergangen ist, aber nicht wieviel der Arbeit getan wurde. Der Thread weiss wieviel Arbeit getan wurde, aber der Fortschritt ist nicht unbedingt regelmaessig.


Alle Zeitangaben in WEZ +1. Es ist jetzt 15:46 Uhr.

Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz