![]() |
Delphi-Version: 2005
Überschreiben von TThread.Terminate
Ich stehe gerade vor folgendem "Problem". Ein wirkliches Problem ist es nicht, da ich Alternativen habe, es zu umgehen, trotzdem würde ich gerne wissen, warum mein erster Ansatz so nicht funktioniert.
Ich habe eine eigene Thread-Klasse geschrieben, die (logischerweise) von TThread abgeleitet ist. Ich möchte gerne die Methode TThread.Terminate aus dem public-Bereich überschreiben, weil bei deren Aufruf intern in meiner eigenen Thread-Klasse noch etwas mehr passieren soll, als nur das FTerminated-Feld auf True zu setzen. Aber auch das soll natürlich weiterhin passieren. Daher habe ich TThread.Terminate folgendermaßen überschrieben:
Delphi-Quellcode:
Das Problem ist, dass TThread.Terminate scheinbar übersprungen wird und von dem inherited nicht aufgerufen. Ein Breakpoint innerhalb von TThread.Terminate wird grün dargestellt und deshalb beim Debuggen auch nie erreicht. Woran liegt das? Kann man TThread.Terminate nicht überschreiben und falls nicht, warum?
interface
type TMeinThread = class(TThread) private ... public procedure Terminate; // override hier ja nicht nötig, da nicht virtual end; implementation procedure TMeinThread.Terminate; begin // TThread.Terminate aufrufen, um FTerminated auf True zu setzen inherited; // anschließend noch alles weitere machen ... end; end. Danke für die Aufklärung :) |
AW: Überschreiben von TThread.Terminate
Die Antwort hast du schon selber gegeben durch deinen Kommentar hinter Terminate.
Wenn intern Terminate aufgerufen wird, dann wird das TThread.Terminate aufgerufen und nicht TMeinThread.Terminate. Dazu müsste die Methode in TThread schon virtual sein. |
AW: Überschreiben von TThread.Terminate
Delphi-Quellcode:
Genau falsch ... es muß heißen
// override hier ja nicht nötig, da nicht virtual
"override hier ja nicht möglich, da nicht virtual" Heißt also, du kannst es nicht überschreiben Und TThread ruft nur das ihm bekannte Terminate auf (deines kennt er nicht). Wie wäre es mit einem Eventhandler für OnTerminate? |
AW: Überschreiben von TThread.Terminate
Zitat:
Virtuelle Methoden sind ja nur wichtig, wenn von deiner Elternklasse in eine deiner Methoden gesprungen werden soll. Aber Terminate ruft man ja nur von außen auf, deswegen einfach verdecken, fertsch. |
AW: Überschreiben von TThread.Terminate
Zitat:
|
AW: Überschreiben von TThread.Terminate
Zitat:
Zitat:
Zitat:
|
AW: Überschreiben von TThread.Terminate
Wenn nich virtuell dann gibt es auch keine VMT
|
AW: Überschreiben von TThread.Terminate
Zitat:
Aber ein kurzes Üüberlegen, wann der Fall eintritt, sagt mir, dass man dann den Thread während des Betriebes von außen abschießen muss. Böse Sache, dass. |
AW: Überschreiben von TThread.Terminate
Zitat:
Wenn man "von Außen" eine TThread Variable hat, und diese dann aber mit einem TmeinThread belegt und .terminate aufruft, wird trotzdem nur TThread.Terminate aufgerufen. |
AW: Überschreiben von TThread.Terminate
Andere Frage: wieso kann ich in TThread.Terminate auf der (einzigen) Zeile
Delphi-Quellcode:
keinen Breakpoint setzen, der auch angesteuert wird?
FTerminated := True;
|
AW: Überschreiben von TThread.Terminate
@jfheins: Mist, naja virtuelle Biere sind ja recht günstig.
Aber dann hat TThread echt einen Designfehler (also noch einen mehr). Denn wo kann ich sonst zum Terminate noch etwas anfügen? Ich benutze diese Methode (hatte mich anfangs auch gewundert warum nicht virtuell, und mir dann meine, diese, Erklärung zurechtgelegt) recht häufg, wenn zum Beispiel mein Thread schläft auf Grund von:
@MatthiasR Menu - Projektoptionen -> Debug-DCUs verwenden |
AW: Überschreiben von TThread.Terminate
Die Prozedur Terminate setzt nur .Terminated auf true.
Ob und wie der Thread das nun intern beachtet ist egal. Terminate/Terminated beendet die Threadverarbeitung nicht. Terminated sagt nur "Hallo lieber Thread, würdest du dich bitte mal beenden?" Also eigentlich sehe ich demnach auch keinen Grund, warum dieses überschreibar sein soll, da man es ja Threadintern dennoch anders behandeln kann (z.B. einfach ignorieren oder mit was Anderem verknüpfen). Es muß ja nicht sein, daß man alles virtuell macht und so die VMT unnütz vergrößert. - bei WaitForSingleObject und Co. läßt sich auch noch eine weitere Abbruchbedingung einbauen. - ReadFile ließe sich Asynchron verarbeiten - usw. |
AW: Überschreiben von TThread.Terminate
Zitat:
Zitat:
|
AW: Überschreiben von TThread.Terminate
Zitat:
Zum Glück hat ein Thread ein OnTerminate Event, wie schade nur, dass das erst aufgerufen wird, nachdem der Thread terminated wurde, und nicht zu dem Zeitpunkt, wo Terminate aufgerufen wurde. Wie man es auch dreht und wendet, es ist schlecht, dass Terminate nicht virtual ist. |
AW: Überschreiben von TThread.Terminate
Es ging Frank um die Tatsache, dass die Methode nur das Feld setzt und nicht den Thread beendet. Diese Funktionalität gehört in den Threadcode ( Reagieren auf die Änderung von .Terminated)
|
AW: Überschreiben von TThread.Terminate
Zitat:
Zitat:
|
AW: Überschreiben von TThread.Terminate
@himi
Steve hat ja schon alles gesagt, noch Ergänzungen: Zitat:
Zitat:
Zitat:
Zitat:
Ich nutze es ständig weil es eben nicht anders geht, ansonsten kann ich auch gleich jedwedes Threading mir sparen. |
AW: Überschreiben von TThread.Terminate
Zitat:
Bei einer TThread-Variable würde wieder das "Alte" aufgerufen. Zitat:
Zitat:
Wie, womit wird denn die Datei runtergeladen? Viele der Wege bieten es ja an, daß man wärend des Downloads Ereignisse bekommt oder wo man stückchenweise in einen Puffer lesen kann und dann dazwischen die Abbuchbedingung mit einbindet. |
AW: Überschreiben von TThread.Terminate
Zitat:
Zitat:
|
AW: Überschreiben von TThread.Terminate
Du kannst nach wie vor die Vorgängermethode aufrufen. Mach ich ja, wie gesagt, auch ständig.
Du kannst dir ja mal bspw. mein DosCommand ansehen: ![]() |
AW: Überschreiben von TThread.Terminate
Und wie geht das? Mit inherited?
|
AW: Überschreiben von TThread.Terminate
Zitat:
Was nicht einkompiliert ist (weil es z.B. nicht verwendet wird), das kann auch nicht im Debugger mit einem Haltepunkt versehn werden. Sind denn in dieser Procedur die kleinen blauen Pünktchen zu sehn? (oder überhaupt irgendwo in der ganzen Unit) |
AW: Überschreiben von TThread.Terminate
Zitat:
Delphi-Quellcode:
Es gibt da auch noch ein größeres Beispiel.
constructor TReadPipe.Create(Aread_stdout,Awrite_stdout:THandle);
begin inherited Create(false); FEvent:=TEvent.Create(nil,false,false,''); FSyncString:=TSyncString.Create; Fread_stdout:=Aread_stdout; Fwrite_stdout:=Awrite_stdout; freeonterminate:=true; end; destructor TReadPipe.Destroy; begin FEvent.Free; FSyncString.Free; inherited; end; procedure TReadPipe.Execute; var Buf:array[0..1023] of byte; bread:Cardinal; s:string; begin repeat ReadFile(Fread_stdout, Buf, length(buf), bread, nil); //wait for input if terminated then exit; setlength(s,bread); move(buf[0],s[1],bread); FSyncstring.Add(s); FEvent.SetEvent; until terminated; end; procedure TReadPipe.Terminate; const fin='fin'; var bwrite:Cardinal; begin inherited; WriteFile(Fwrite_stdout,fin,length(fin),bwrite,nil); end; |
AW: Überschreiben von TThread.Terminate
Zitat:
Und nein, in der ganzen Classes-Unit werden keine blauen Pünktchen angezeigt, auch wenn die Debug-DCUs aktiviert sind. Zitat:
|
AW: Überschreiben von TThread.Terminate
Du hast nicht zufällig "build with runtime packages" an, oder?
|
AW: Überschreiben von TThread.Terminate
Zitat:
Zitat:
|
AW: Überschreiben von TThread.Terminate
Ok, das ist nun ein Problem, was mit der Ursprungsfrage nix mehr zu tun hat.
Ich kann nur sagen: dass du nicht in die Classes.pas debuggen kannst, hat mit den Runtime Packages zu tun, die sind nämlich Release und keine Debug Builds. Es gibt wohl ne Möglichkeit, sich Debug Builds der Delphi eigenen Runtime Packages zu basteln, aber das ist recht kompliziert, wenn ich mich recht erinnere. Wenn du also dein Projekt ohne Packages kompilierst, und debug dcus anhakst, kannst du auch durch die ganzen rtl/vcl sourcen debuggen. Wenn du also auf eine Variable von TMeinThread Terminate aufrufst wird mit Sicherheit über inherited die verdeckte Terminate Methode von TThread aufgerufen. Du darfst nur keine Variable vom Typ TThread haben, dann würde nur die von dort aufgerufen. |
AW: Überschreiben von TThread.Terminate
Ja, das stimmt, das ist wieder ein anderes Problem und mein ursprüngliches wäre nun geklärt. Danke für die ausführliche Erklärung! Klar, wenn in den Runtime Packages keine Debug Symbole sind, und ich das Projekt aktuell OHNE Runtime Packages nicht compilieren kann, dann wird das schwierig mit dem Debuggen der Delphi-eigenen Klassen.
|
AW: Überschreiben von TThread.Terminate
@Stevie
debuggen in classes ... wenn Du classes.pas zu debuggen in Dein Projektverzeichnis kopierst. |
AW: Überschreiben von TThread.Terminate
Zitat:
Einmal das Selbsteingebundene/Kopierte und dann verwenden die restlichen Delphi/VCL-Units dennoch die originale Classes.pas. Heißt also, daß beim Debuggen in diesem Fall eher mit Problemem zu rechnen ist, da Einiges die Originale und Anderes die Kopie verwendet. |
Alle Zeitangaben in WEZ +1. Es ist jetzt 07:06 Uhr. |
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz