AGB  ·  Datenschutz  ·  Impressum  







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

Threadstatus abfragen

Ein Thema von Schwedenbitter · begonnen am 3. Jul 2008 · letzter Beitrag vom 13. Aug 2008
Antwort Antwort
Seite 1 von 3  1 23      
Schwedenbitter

Registriert seit: 22. Mär 2003
Ort: Finsterwalde
622 Beiträge
 
Turbo Delphi für Win32
 
#1

Threadstatus abfragen

  Alt 3. Jul 2008, 12:45
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:
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.
Gruß, Alex
Alex Winzer
  Mit Zitat antworten Zitat
Yellow579
(Gast)

n/a Beiträge
 
#2

Re: Threadstatus abfragen

  Alt 3. Jul 2008, 13:17
Hallo Schwedenbitter!

Zu deiner eigentlichen Frage: Ob der Thread an sich existiert, kannst du mit der Überprüfung der Instanzenvariablen erreichen (<> nil, sprich Delphi-Referenz durchsuchenAssigned()). Voraussetzung dafür ist aber, dass diese Variable ordentlich auf nil gesetzt wird, wenn der Thread beendet wird. Dies kannst du u.a. dadurch erreichen, in dem du dem Thread ein OnTerminate Ereignis zuweist und darin diese Variable auf nil setzt. Damit kannst du die Existenz soweit sicher vom Hauptprogramm aus abfragen. Und wenn dieser existiert bleibt nur noch die Frage bestehen, ob er z.Z. suspendiert ist. Dies kannst du mit der Eigenschaft Delphi-Referenz durchsuchenSuspended abfragen.

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 Delphi-Referenz durchsuchenSynchronize von TThread.

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
  Mit Zitat antworten Zitat
Benutzerbild von Luckie
Luckie

Registriert seit: 29. Mai 2002
37.621 Beiträge
 
Delphi 2006 Professional
 
#3

Re: Threadstatus abfragen

  Alt 3. Jul 2008, 13:37
Zitat von Yellow579:
Hallo Schwedenbitter!

Zu deiner eigentlichen Frage: Ob der Thread an sich existiert, kannst du mit der Überprüfung der Instanzenvariablen erreichen (<> nil, sprich Delphi-Referenz durchsuchenAssigned()). Voraussetzung dafür ist aber, dass diese Variable ordentlich auf nil gesetzt wird, wenn der Thread beendet wird. Dies kannst du u.a. dadurch erreichen, in dem du dem Thread ein OnTerminate Ereignis zuweist und darin diese Variable auf nil setzt.
Bist du sicher dass das geht? Du ziehst dem Threadobjekt ja quasi den Teppich unter den Füßen weg, während es noch existiert.
Michael
Ein Teil meines Codes würde euch verunsichern.
  Mit Zitat antworten Zitat
Yellow579
(Gast)

n/a Beiträge
 
#4

Re: Threadstatus abfragen

  Alt 3. Jul 2008, 13:52
Hallo Luckie!

Zitat von Luckie:
Bist du sicher dass das geht? Du ziehst dem Threadobjekt ja quasi den Teppich unter den Füßen weg, während es noch existiert.
Ich bin erschüttert, weil das was du schreibst kann nur zu Problemen führen, wenn du aus dem Thread heraus auf die externe (in der Form) liegende eigene Instanzenvariable zugreifst. Aber ich denke mal, du hast da nur einen kleinen Denkfehler.

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:
with TObject.Create do
begin
  Whatever;
  Free;
end;
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.

/EDIT: Gegenfrage: Nach deiner Logik fortgeführt: Was macht die Instanz, wenn ich diese gleich in 10 Variablen ablege?

Delphi-Quellcode:
var
  obj1, obj2, ... , obj10: TObject;
begin
  obj1 := TObject.Create;
  obj2 := obj1;
  obj3 := obj1;
  ...
  obj10 := obj1;
end;
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...

Gruss
Yellow
  Mit Zitat antworten Zitat
Schwedenbitter

Registriert seit: 22. Mär 2003
Ort: Finsterwalde
622 Beiträge
 
Turbo Delphi für Win32
 
#5

Re: Threadstatus abfragen

  Alt 3. Jul 2008, 14:07
Mist! Ich wollte doch keinen Krieg provozieren.
Geht das hier erstmal für den Anfang:

Delphi-Quellcode:
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;
Der Rest der Antwort von Yellow ist mir zu hoch für den Anfang.

Gruß, Alex
Alex Winzer
  Mit Zitat antworten Zitat
Benutzerbild von Luckie
Luckie

Registriert seit: 29. Mai 2002
37.621 Beiträge
 
Delphi 2006 Professional
 
#6

Re: Threadstatus abfragen

  Alt 3. Jul 2008, 14:17
Zitat von Yellow579:
Hallo Luckie!

Zitat von Luckie:
Bist du sicher dass das geht? Du ziehst dem Threadobjekt ja quasi den Teppich unter den Füßen weg, während es noch existiert.
Ich bin erschüttert, weil das was du schreibst kann nur zu Problemen führen, wenn du aus dem Thread heraus auf die externe (in der Form) liegende eigene Instanzenvariable zugreifst. Aber ich denke mal, du hast da nur einen kleinen Denkfehler.
Ich verstehe jetzt den Zusammenhang nicht so ganz. Ich mache gar nichts. Ich stelle nur in Frage, ob der Vorschlag meines Vorposters funktionieren kann. Er will ja die Objektvariable in einem Ereignis der Objektvariablen selber auf nil setzen.
Michael
Ein Teil meines Codes würde euch verunsichern.
  Mit Zitat antworten Zitat
DelphiManiac

Registriert seit: 5. Dez 2005
742 Beiträge
 
#7

Re: Threadstatus abfragen

  Alt 3. Jul 2008, 14:44
@Yellow579

Zitat:
Hallo Luckie!

Luckie hat folgendes geschrieben:
Bist du sicher dass das geht? Du ziehst dem Threadobjekt ja quasi den Teppich unter den Füßen weg, während es noch existiert.


Ich bin erschüttert, weil das was du schreibst kann nur zu Problemen führen, wenn du aus dem Thread heraus auf die externe (in der Form) liegende eigene Instanzenvariable zugreifst. Aber ich denke mal, du hast da nur einen kleinen Denkfehler.
Ich glaube hier ist jemand in der Spalte verrutscht, der Beitrag kam ja nicht von Luckie, sonder von Schwedenbitter, selbst wenn Luckie das über Threads geschrieben hätte, dann würde es wahrscheinlich sogar stimmen ...

Viele Grüße
DM
  Mit Zitat antworten Zitat
Yellow579
(Gast)

n/a Beiträge
 
#8

Re: Threadstatus abfragen

  Alt 3. Jul 2008, 15:49
Hallo Luckie, hallo DelphiManiac!

Ich zitiere nochmal den gesamten Beitrag:

Zitat von Luckie:
Zitat von Yellow579:
Hallo Luckie!

Zitat von Luckie:
Bist du sicher dass das geht? Du ziehst dem Threadobjekt ja quasi den Teppich unter den Füßen weg, während es noch existiert.
Ich bin erschüttert, weil das was du schreibst kann nur zu Problemen führen, wenn du aus dem Thread heraus auf die externe (in der Form) liegende eigene Instanzenvariable zugreifst. Aber ich denke mal, du hast da nur einen kleinen Denkfehler.
Ich verstehe jetzt den Zusammenhang nicht so ganz. Ich mache gar nichts. Ich stelle nur in Frage, ob der Vorschlag meines Vorposters funktionieren kann. Er will ja die Objektvariable in einem Ereignis der Objektvariablen selber auf nil setzen.
Wie man sieht, zitiere ich Luckie und dies steht auch so in seinem Beitrag.

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 Sprüchen wie RTFM und ich gebe einem anderen Recht, weil er mehr Postings hat. Kleinlaut gibs dann nachher die Korrektur.
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
  Mit Zitat antworten Zitat
PMM

Registriert seit: 17. Feb 2005
101 Beiträge
 
#9

Re: Threadstatus abfragen

  Alt 3. Jul 2008, 15:59
... 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
  Mit Zitat antworten Zitat
Benutzerbild von Luckie
Luckie

Registriert seit: 29. Mai 2002
37.621 Beiträge
 
Delphi 2006 Professional
 
#10

Re: Threadstatus abfragen

  Alt 3. Jul 2008, 16:03
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:
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;
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.

Jetzt, wo ich den Code vor mir habe, ist mir auch klar geworden, dass das natürlich ohne Probleme funktioniert muss.
Michael
Ein Teil meines Codes würde euch verunsichern.
  Mit Zitat antworten Zitat
Antwort Antwort
Seite 1 von 3  1 23      


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 05:27 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