AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Thema durchsuchen
Ansicht
Themen-Optionen

[D7] EThread: Thread-Fehler: (6)

Ein Thema von Hobbycoder · begonnen am 14. Feb 2023 · letzter Beitrag vom 15. Feb 2023
Antwort Antwort
Hobbycoder

Registriert seit: 22. Feb 2017
961 Beiträge
 
#1

[D7] EThread: Thread-Fehler: (6)

  Alt 14. Feb 2023, 18:12
Hallo Leute,
ich habe in einem älteren Programm einen (für mich) seltsamen Fehler. Nach ca. einem halben Tag Laufzeit kommt es zu einem Thread-Fehler. Der Callstack führt mich zu einem TThread.Create. Es handelt sich bei diesem Thread, der in regelmäßigen Abständen eine Referenzliste aus einer Datenbank abruft um diese aktuell zu halten. Von diesen Threads gibt es mehrere, weil teilweise unterschiedliche Intervalle notwendig sind. Der Thread wird bis zum Mittag einige hundert mal aufgerufen und läuft fehlerfrei durch.
Vor dem Start des Threads wird geprüft ob er aus irgendeinem Grund noch läuft und wird beendet.
Beendet wird er so:
Delphi-Quellcode:
proceudre Tfrm_main.KillThreadUrlaubsGrund;
var
  ThreadHandle: THandle;
begin
  if ThLoadUrlaubsGrund<>nil then
  begin
    ThreadHandle:=ThLoadUrlaubsGrund.Handle;
    ThLoadUrlaubsGrund.OnFinished:=nil;
    ThLoadUrlaubsGrund.OnNewUrlaubsgrundList:=nil;
    ThLoadUrlaubsGrund.Terminate;
    WaitForSingleObject(ThreadHandle, 500);
    ThLoadUrlaubsGrund:=nil;
  end;
end;
Gestarte wird er so:
Delphi-Quellcode:
  
  KillThreadUrlaubsGrund;
  ThLoadUrlaubsGrund:=TThreadLoadUrlaubsgrundList.Create(True, dm1.Con);
  HandleUrlaubsgrundListThread:=ThLoadUrlaubsGrund.Handle;
  ThLoadUrlaubsGrund.OnFinished:=OnFinishUrlaubsGrundThread;
  ThLoadUrlaubsGrund.OnNewUrlaubsgrundList:=OnUpdateUrlaubsGrundList;
  WritePrivateLog('Start Thread UrlaubsGrund ('+IntToStr(HandleUrlaubsgrundListThread)+')');
  ThLoadUrlaubsGrund.Resume;
Der Fehler tritt dann im Create des TThreadLoadUrlabusgrundList auf:
Delphi-Quellcode:
constructor TThreadLoadUrlaubsgrundList.Create(Suspended: Boolean;
  Con: TZConnection);
begin
  inherited Create(Suspended); //<--------- Hier zeigt Callstack den Fehler Thread-Fehler: (6)
  FDBHost:=Con.HostName;
  FDBPort:=Con.Port;
  FDBUser:=Con.User;
  FDBPass:=Con.Password;
  FDBDatabase:=Con.Database;
  FDBProtocol:=Con.Protocol;
  self.FreeOnTerminate:=True;
end;
Beende ich den Thread falsch? Der Thread läuft mit FreeOnTerminate=True.
Als letzte Zeile im Execute des Thread rufe ich noch einen Event auf, der im Aufrufthread die Variable des Thread auf nil setzt. Sollte also der Thread, aus welchem Grund auch immer, länger brauchen als der Aufrufintervall definiert ist, soll er über die Methode KillThreadUrlaubsGrund gekillt werden.

Vielleicht steh ich ja auf dem Schlauch, und mache irgendwas grundlegend falsch.
Gruß Hobbycoder
Alle sagten: "Das geht nicht.". Dann kam einer, der wusste das nicht, und hat's einfach gemacht.
  Mit Zitat antworten Zitat
peterbelow

Registriert seit: 12. Jan 2019
Ort: Hessen
704 Beiträge
 
Delphi 12 Athens
 
#2

AW: [D7] EThread: Thread-Fehler: (6)

  Alt 15. Feb 2023, 17:39
So direkt sehe ich da keine Auffälligkeit (außer der Verwendung von Resume anstelle von Start), aber das ganze Design ist IMO suboptimal und fehleranfällig, besonders wenn die verwendete DB-Konnektion nicht multithread-tauglich ist.

Anstatt jedesmal einen neuen Thread zu erzeugen würde ich einmal zu Beginn einen Thread erzeugen der dann in einer Schleife in seiner Execute Methode auf einen Event (TSimpleEvent z. B.) wartet, mit einem Timeout, der dem gewünschten Aktivitätsintervall entspricht. Wenn der Event "aufwacht" prüft der Kode zuerst, ob Terminated True ist; wenn ja verläßt er die Schleife und der Thread beendet sich. Wenn Terminated False ist prüft der Kode den Rückgabewert der WaitFor-Methode des Events; das sagt ihm, wieso der Event ausgelöst hat. Wenn das der Timeout war setzt der Kode den Event wieder auf "not signalled" und ruft dann die Methode auf, die die Arbeit mit der Datenbank erledigt. Wenn es nicht der Timeout war sollte die Arbeitsschleife ebenfalls beendet werden. Dadurch kann man den Thread kontrolliert von außen beenden, in dem man den Event auslöst.
Peter Below
  Mit Zitat antworten Zitat
Benutzerbild von himitsu
himitsu

Registriert seit: 11. Okt 2003
Ort: Elbflorenz
44.184 Beiträge
 
Delphi 12 Athens
 
#3

AW: [D7] EThread: Thread-Fehler: (6)

  Alt 15. Feb 2023, 18:50
Es gibt eine globale Variable mit der Referenz auf die TThread-Instanz,
aber gleichzeitig wird durch FreeOnTerminate irgendwann die Instanz gelöscht und diese Variable wird ungültig.

Auf solche Variablen darf man bei Verwendung von FreeOnTerminate eigentlich nie wieder drauf zugreifen (besser es gibt erst garnicht solche Variablen),
es sei denn man gestaltet diese Zugriffe thread-safe (CriticalSection), also um das Auslesen, als auch um das :=nil, welches am Ende des Threads von Diesem gemacht werden muß.

Auch das extern gespeicherte Thread-Handle ist nach dem Ende des Threads ungültig.
Hier könnte man sich via DuplicateHandle ein eigenes Handle besorgen und damit weiterarbeiten.
Kurz nach Erstellen/Start des Threads (wenn dieser "garantiert" länger läuft), oder besser innerhalb des Threads dupplizieren, also so lange das Thread.Handle garantiert gültig ist.
$2B or not $2B
  Mit Zitat antworten Zitat
Antwort Antwort


Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 09:11 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