![]() |
Threadstatus abfragen
Hallo,
ich habe hier (immer noch) Delphi 6. Ich möchte gern etwas in einem Thread ablaufen lassen und habe dazu ein kleines Testprogramm geschrieben. Für Hinweise zur Verbesserung im Allgemeinen bin ich zugänglich. Nun aber zu meiner Frage: Gibt es bei TThread eine Eigenschaft oder sonstwas, womit ich ohne Probleme abfragen kann, ob der Thread bereits existiert und ggf. nur angehalten ist? Bislang löse ich das über eine globale Variable, was mir aber nicht wirklich gefällt. Das Formular besteht aus einem TLabel für die Ausgabe und 3 Buttons für "Start", "Anhalten" unmd "Beenden" des Threads:
Delphi-Quellcode:
Gruß, Alex
Unit _Main;
Interface Uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls; Type TTestThread = Class(TThread) Procedure Execute; override; End; TForm1 = Class(TForm) Label1 : TLabel; Button1 : TButton; Button2 : TButton; Button3 : TButton; Procedure FormCreate(Sender: TObject); Procedure Button1Click(Sender: TObject); Procedure Button2Click(Sender: TObject); Procedure Button3Click(Sender: TObject); End; Var Form1 : TForm1; Exists : Boolean; SecondProcess : TTestThread; Implementation {$R *.dfm} Procedure TForm1.FormCreate(Sender: TObject); Begin Exists:=False; End; Procedure TTestThread.Execute; Var I : Integer; Begin For I:=0 To MaxInt Do Begin Form1.Label1.Caption:=IntToStr(I); If Terminated Then Begin Exit; End; End; Form1.Label1.Caption:='Thread beendet.'; End; Procedure TForm1.Button1Click(Sender: TObject); Begin Button1.Enabled:=False; Button2.Enabled:=True; Button3.Enabled:=True; If Not Exists Then // Thread existiert schon? Begin SecondProcess:=TTestThread.Create(True); SecondProcess.Priority:=tpLower; Exists:=True; End; SecondProcess.Resume; End; Procedure TForm1.Button2Click(Sender: TObject); Begin SecondProcess.Suspend; Button1.Enabled:=True; Button2.Enabled:=False; Label1.Caption:='Thread angehalten.'; End; Procedure TForm1.Button3Click(Sender: TObject); Begin SecondProcess.Terminate; Button3.Enabled:=False; Button2.Enabled:=False; Button1.Enabled:=True; Exists:=False; Label1.Caption:='Thread beendet.'; End; End. |
Re: Threadstatus abfragen
Hallo Schwedenbitter!
Zu deiner eigentlichen Frage: Ob der Thread an sich existiert, kannst du mit der Überprüfung der Instanzenvariablen erreichen (<> nil, sprich ![]() ![]() Und nun noch ein paar dringliche Hinweise: Der Thread läuft asynchron zu dem VCL Hauptthread und somit allen anderen VCL Aktivitäten. Von daher müssen Zugriffe auf Elemente des anderen Threads (VCL Mainthread, besitzt jede VCL Anwendung) synchronisiert werden. Mit anderen Worten: Es ist strengstens verboten auf VCL Elemente des VCL Threads von deinem Thread aus zu zu greifen. Ganz speziell sind es in deinem Code die Zugriffe auf Label1. Abhilfe schafft hier die Methode ![]() Dann sollte man die Verwendung von globalen Variablen (wie z.B. Form1) grundlegend vermeiden. Wenn, dann übergebe die Instanz und halte sie lokal im Thread (aber wie gesagt: ausschliesslich synchronisierte Zugriffe!). Vor allem ist es unverständlich, warum du z.B. Exists und SecondProcess nicht als Member des Formulars definiert hast. Instanziier eine zweite Form1 und du hast die misere, da alles doppelt ist, nur die beiden Variablen nicht - die gibs nur einmal und der erste Thread ist auch speichertechnisch verloren, da seine Instanz verloren ist. Dein Threadcode würde mit einer While Schleife (mit 2 Bedingungen: i Endwertvergleich & Terminated) deutlich besser umsetzbar sein als der harte Exit auf Terminated im jetzigen Code. Dann beachte bitte die Hinweise, denn du solltest bei der Execute Methode des Threads einen Hinweis bekommen, dass die Sichtbarkeit der überschriebenen Methode nicht übereinstimmen. Execute ist im protected Abschnitt deklariert und du überschreibst diese aber im public (afair vllt. sogar auch published) Bereich der Klasse. Gruss Yellow |
Re: Threadstatus abfragen
Zitat:
|
Re: Threadstatus abfragen
Hallo Luckie!
Zitat:
Ein Objekt greift soweit niemals auf seine eigene Instanzenvariable zu, somit kann das sonstwas sein. Genausogut nil. Nach Frage zu urteilen, sollte es in deinen Augen auch niemals folgendes funktionieren, da es erst gar keine Variable gibt, in der die Instanz abgelegt wird:
Delphi-Quellcode:
Die Instanzenvariable ist nur ein Pointer und kann sonstwo hinzeigen, das interessiert die Instanz im Speicher (deren Adresse in der Variablen hinterlegt ist) herzlich wenig.
with TObject.Create do
begin Whatever; Free; end; /EDIT: Gegenfrage: Nach deiner Logik fortgeführt: Was macht die Instanz, wenn ich diese gleich in 10 Variablen ablege?
Delphi-Quellcode:
Deine Logik hätte aber umgesetzt ihren Reiz, weil dann wären z.B. nach einem FreeAndNil() auch gleich alle anderen Instanzenvariablen nil, egal wo diese liegen. Das hätte für manchen Anfänger schon seinen Reiz...
var
obj1, obj2, ... , obj10: TObject; begin obj1 := TObject.Create; obj2 := obj1; obj3 := obj1; ... obj10 := obj1; end; Gruss Yellow |
Re: Threadstatus abfragen
Mist! Ich wollte doch keinen Krieg provozieren.
Geht das hier erstmal für den Anfang:
Delphi-Quellcode:
Der Rest der Antwort von Yellow ist mir zu hoch für den Anfang.
Procedure TTestThread.Ausgabe;
Begin Form1.Label1.Caption:=S; End; Procedure TTestThread.Execute; Var I : Integer; Begin I:=0; While (I<=MaxInt) And Not Terminated Do Begin S:=FormatFloat('#,##0',I); Synchronize(Ausgabe); Inc(I); End; S:='Thread beendet.'; Synchronize(Ausgabe); End; Gruß, Alex |
Re: Threadstatus abfragen
Zitat:
|
Re: Threadstatus abfragen
@Yellow579
Zitat:
Viele Grüße DM |
Re: Threadstatus abfragen
Hallo Luckie, hallo DelphiManiac!
Ich zitiere nochmal den gesamten Beitrag: Zitat:
Vorposter = Yellow579 = ich. Der Vorschlag kam auch von mir, somit Vorposter = Yellow579 = ich. Und welche Spalte meinst du bitteschön? Ich habe hier nur eine... Und zu der Frage: Was hat die Instanzenvariable mit einem Event einer Instanz zu tun? Die Instanz referenziert niemals die Instanzenvariable, weil es eine n:1 Beziehung ist. Umgekehrt referenziert die Instanzenvariable die Instanz... Und wenn diese Instanz eine Methode aufruft, was die Closure's ja nunmal nur sind, dann wird self über den Stack übergeben und nicht ein Pointer auf die Instanzenvariable. Diese spielt in der gesamten Abarbeitung überhaupt keine Rolle, von daher verstehe ich überhaupt nicht wie du, Luckie, auf die Idee kommst, dass es was miteinander zu tun hat. Ich kann in jedem Ereignis eines Objektes dessen Instanzenvariable verändern (somit auch nil setzen), wie ich lustig bin. Spätestens beim Zugriff (von außen wohlgemerkt), habe ich dann mehr oder minder ein Problem, aber mit nil und einer Abprüfung kein Problem (siehe Beitrag zuvor). Und ein Zugriff von innen, also aus der Instanz heraus auf die Variable - ich kann mich nur wiederholen - findet nicht statt. Einzige Möglichkeit: es wurde explizit so reinprogrammiert (siehe Nutzung globaler Instanzenvariablen) - und dies ist der einzige Weg und die einzige Begründung, welche eine solche Frage aufkommen lassen kann. Von daher die Erschütterung über die Frage. [OT] Es ist erschütternd, da kommt man in dieses Forum und teilt sein Wissen mit und es wird einem Widersprochen - aber dann gleich deutlich mit ![]() Hier weise ich eindeutig mit Zitaten auf den bezogenen Inhalt hin und schon meint man, ich lese schief. Der Inhalt war doch ganz genau auf diesen Beitrag zugeschnitten und entsprechend geschrieben. Es ist eindeutig, dass ich mich mit keinem Wort auf den Beitrag vom Threadersteller beziehe. Und dieser hat keinen solchen Vorschlag gemacht wie ich. Bitte, lest die Beiträge in Ruhe durch, durchdenkt sie und dann postet. Am besten auch vorher mal ausprobieren und nicht gleich Blasphemie Ketzer schreien... Witziges Forum hier... [/OT] Grüsse Yellow |
Re: Threadstatus abfragen
... Er will ja die Objektvariable in einem Ereignis der Objektvariablen selber auf nil setzen.
Das ist zwar etwas "gewöhnungsbedürftig" aber an dieser Stelle völlig OK denke ich. Es bedeutet, dass das Objekt, zumindest über diese Objektvariable, nicht mehr erreichbar ist. Damit wird, im diskutierten Fall, "nach außen" signalisiert, dass der Thread nun tatsächlich beendet wurde - was ja asynchron über das Betriebssytem erfolgt und ansonsten gar nicht so einfach festzustellen ist. Und das alles ganz unabhängig davon wer wann, warum was gepostet hat :) PMM |
Re: Threadstatus abfragen
Noch mal, ich habe nicht widersprochen, sondern nur etwas in Frage gestellt. Du hast folgendes vorgeschlagen:
Delphi-Quellcode:
unit Unit2;
interface uses SysUtils, Classes; type TTest = class(TThread) private { Private-Deklarationen } protected procedure Execute; override; end; implementation { Wichtig: Methoden und Eigenschaften von Objekten in VCL oder CLX können nur in Methoden verwendet werden, die Synchronize aufrufen, z.B.: Synchronize(UpdateCaption); wobei UpdateCaption so aussehen könnte: procedure TTest.UpdateCaption; begin Form1.Caption := 'In einem Thread aktualisiert'; end; } { TTest } procedure TTest.Execute; var i: Integer; s: String; begin for i := 0 to 9999 do begin s := s + IntToStr(i); end; end; end.
Delphi-Quellcode:
Und ich habe in Frage gestellt, ob man in einem Ereignis eines Objektes, selbiges auf nil setzen kann. Hintergrund war der, dass wenn man in einem Destruktor die Objektreferenz auf nil setzt, es zu einer Exception kommt. Das hatte ich im Hinterkopf.
unit Unit1;
interface uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls; type TForm1 = class(TForm) Button1: TButton; procedure Button1Click(Sender: TObject); private { Private-Deklarationen } TestThread: TThread; procedure OnTerminate(Sender: TObject); public { Public-Deklarationen } end; var Form1: TForm1; implementation {$R *.dfm} uses Unit2; procedure TForm1.Button1Click(Sender: TObject); begin TestThread := TTest.Create(True); TestThread.OnTerminate := OnTerminate; TestThread.Resume; end; procedure TForm1.OnTerminate(Sender: TObject); begin TestThread := nil; end; Jetzt, wo ich den Code vor mir habe, ist mir auch klar geworden, dass das natürlich ohne Probleme funktioniert muss. |
Alle Zeitangaben in WEZ +1. Es ist jetzt 02:49 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 by Thomas Breitkreuz