AGB  ·  Datenschutz  ·  Impressum  







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

Threads "korrekt" beenden

Ein Thema von FAlter · begonnen am 30. Jan 2009 · letzter Beitrag vom 31. Jan 2009
Antwort Antwort
Seite 1 von 2  1 2      
Benutzerbild von FAlter
FAlter

Registriert seit: 21. Jul 2004
Ort: Ostfildern
1.096 Beiträge
 
FreePascal / Lazarus
 
#1

Threads "korrekt" beenden

  Alt 30. Jan 2009, 18:11
Hi,

es geht um folgendes:

Angenommen, ich habe eine Klasse von TThread abgeleitet und verwende sie so einfach wie möglich, indem ich einfach den Konstruktor aufrufe und den Rest dem Thread überlasse. FreeOnTerminate wird im Konstruktor auf true gesetzt, sodass der Thread nach seiner Arbeit automatisch zerstört wird.

In meinem Programm steht dann ja nur noch ein TMyThread.Create(...) drin, und da ich es nicht brauche, speichere ich auch das neue Objekt nirgends.

Nun kommt aber irgendwer auf die Idee, das Programm zu beenden während der Thread noch läuft. Dann wird dieser ja sofort abgebrochen.

Schöner wäre es ja, wenn erstmal nur die Methode Terminate des Threads aufgerufen wird und das Programm sich erst dann komplett beendet, wenn die gerade laufenden Threads allesamt auch beendet sind.

Nur wie kann ich das erreichen, wo ich doch keinen Zugriff mehr auf die Objekte habe?


Gibt es einen besseren Ansatz als die laufenden Threads in eine TObjectList einzutragen? Dann müsste ich bei FreeOnTerminate nämlich immer auch noch das OnTerminate entsprechend implementieren, damit sich die Threads auch selbst wieder rauslöschen, ansonsten würde die Liste ja bereits freigegebene Objekte enthalten. Was anderes fällt mir nämlich nicht ein auf das Ende des Threads zu reagieren.

Mfg
FAlter

[edit] Mit WM_QUERYENDSESSION im Thread abfragen geht es nicht unbedingt - es soll für alle Nachfahren von TThread gelten, auch für fremde... [/edit][edit]Und der Thread könnte ja eh nicht schnell genug darauf reagieren, da die Reaktion auch abgebrochen werden würde. [/edit]
Felix Alter
  Mit Zitat antworten Zitat
Benutzerbild von Der.Kaktus
Der.Kaktus

Registriert seit: 22. Jan 2008
Ort: Erfurt
958 Beiträge
 
Delphi 7 Enterprise
 
#2

Re: Threads "korrekt" beenden

  Alt 30. Jan 2009, 18:19
Hi, schau Dir mal folgende Komponente an..vielleicht hilft sie Dir BMThread
Gruss Kaki

Repeat Until true=false;
  Mit Zitat antworten Zitat
Benutzerbild von FAlter
FAlter

Registriert seit: 21. Jul 2004
Ort: Ostfildern
1.096 Beiträge
 
FreePascal / Lazarus
 
#3

Re: Threads "korrekt" beenden

  Alt 30. Jan 2009, 18:31
Hi,

ich will keine Komponente haben, sondern den "normalen" TThread aus der Unit Classes nutzen. Das geht doch recht einfach. Konstruktor schreiben der benötigte Daten entgegennimmt, Execute überschreiben, fertig...

Und bevor die Anwendung ganz stirbt, also z. B. im OnDestroy des Hauptformulars, soll was getan werden, was das Programm dazu veranlässt, für die ganzen unbekannten Threads idealerweise die Methode Terminate aufzurufen und dann soll gewartet werden bis sich die Threads auch wirklich beendet haben.
Wenn ich die Threads irgendwo gespeichert habe, wäre das ja kein Problem, aber was tue ich eben wenn ich die Threads nicht kenne?

Mfg
FAlter
Felix Alter
  Mit Zitat antworten Zitat
alzaimar
(Moderator)

Registriert seit: 6. Mai 2005
Ort: Berlin
4.956 Beiträge
 
Delphi 2007 Enterprise
 
#4

Re: Threads "korrekt" beenden

  Alt 30. Jan 2009, 18:47
Was hält Dich denn davon ab, dir die Instanz des Threads zu merken? Dann kannst Du ihn kontrolliert beenden. Übrigens führt es zu unschönen Seiteneffekten, wenn man Threads nicht selbst terminiert. Im Terminierungscode des Threads werden Resourcen aus der Unit 'Classes' benötigt, die beim Beenden der Anwendung u.U. schon freigegeben, d.h. nicht mehr vorhanden sind. Das kann zu unschönen AV-Meldungen führen, deren Herkunft nur sehr schwer zu ermitteln ist.

Daher solltest Du immer alle Threads VOR Ausführung der Finalisierungssequenz (z.B. im OnClose/OnDestroy deines Hauptformulars) beenden.
"Wenn ist das Nunstruck git und Slotermeyer? Ja! Beiherhund das Oder die Flipperwaldt gersput!"
(Monty Python "Joke Warefare")
  Mit Zitat antworten Zitat
Benutzerbild von FAlter
FAlter

Registriert seit: 21. Jul 2004
Ort: Ostfildern
1.096 Beiträge
 
FreePascal / Lazarus
 
#5

Re: Threads "korrekt" beenden

  Alt 30. Jan 2009, 18:49
Hi,

das heißt also es führt kein Weg daran vorbei die Thread-Objekte zu speichern? Und wenn ich das richtig verstehe ist FreeOnTerminate nicht sinnvoll?

Mfg
FAlter
Felix Alter
  Mit Zitat antworten Zitat
Benutzerbild von Der.Kaktus
Der.Kaktus

Registriert seit: 22. Jan 2008
Ort: Erfurt
958 Beiträge
 
Delphi 7 Enterprise
 
#6

Re: Threads "korrekt" beenden

  Alt 30. Jan 2009, 21:17
Zitat von FAlter:
Hi,

ich will keine Komponente haben, sondern den "normalen" TThread aus der Unit Classes nutzen. Das geht doch recht einfach. Konstruktor schreiben der benötigte Daten entgegennimmt, Execute überschreiben, fertig...

Und bevor die Anwendung ganz stirbt, also z. B. im OnDestroy des Hauptformulars, soll was getan werden, was das Programm dazu veranlässt, für die ganzen unbekannten Threads idealerweise die Methode Terminate aufzurufen und dann soll gewartet werden bis sich die Threads auch wirklich beendet haben.
Wenn ich die Threads irgendwo gespeichert habe, wäre das ja kein Problem, aber was tue ich eben wenn ich die Threads nicht kenne?

Mfg
FAlter
vielleicht was abgucken?
Gruss Kaki

Repeat Until true=false;
  Mit Zitat antworten Zitat
alzaimar
(Moderator)

Registriert seit: 6. Mai 2005
Ort: Berlin
4.956 Beiträge
 
Delphi 2007 Enterprise
 
#7

Re: Threads "korrekt" beenden

  Alt 30. Jan 2009, 22:26
Zitat von FAlter:
das heißt also es führt kein Weg daran vorbei die Thread-Objekte zu speichern?
Wenn Du es 'richtig' machen willst, eigentlich nicht.
Zitat von FAlter:
Und wenn ich das richtig verstehe ist FreeOnTerminate nicht sinnvoll?
Doch, aber nur dann, wenn Du einen Thread hast, der 'nur kurz' etwas macht, oder von dem Du genau weisst, wie (und wann!) er terminiert.
"Wenn ist das Nunstruck git und Slotermeyer? Ja! Beiherhund das Oder die Flipperwaldt gersput!"
(Monty Python "Joke Warefare")
  Mit Zitat antworten Zitat
Benutzerbild von Sir Rufo
Sir Rufo

Registriert seit: 5. Jan 2005
Ort: Stadthagen
9.454 Beiträge
 
Delphi 10 Seattle Enterprise
 
#8

Re: Threads "korrekt" beenden

  Alt 31. Jan 2009, 00:57
Und wenn du sowas nimmst ... eine selbstverwaltende Thread-Klasse?
Delphi-Quellcode:
unit CtrlThread;

interface

uses
  Classes;

type
  TCtrlThread = class( TThread )
  public
    constructor Create(CreateSuspended: Boolean);
    destructor Destroy; override;
  end;

implementation

uses
  Contnrs,
  SyncObjs;

var
  CtrlThreadList : TObjectList;
  CS : TCriticalSection;

procedure KillAllThreads;
var
  CTIdx : Integer;
begin
  while
    ( CtrlThreadList.Count > 0 )
  do
    begin

      CS.Enter;
      try

        for
          CTIdx := 0
        to
          CtrlThreadList.Count - 1
        do
          begin
            TCtrlThread( CtrlThreadList.Items[ CTIdx ] ).FreeOnTerminate := True;
            TCtrlThread( CtrlThreadList.Items[ CTIdx ] ).Terminate;
          end;

      finally
        CS.Leave;
      end;

    end;
end;

{ TCtrlThread }

constructor TCtrlThread.Create(CreateSuspended: Boolean);
begin
  inherited Create( CreateSuspended );

  CS.Enter;
  try
    CtrlThreadList.Add( Self );
  finally
    CS.Leave;
  end;
end;

destructor TCtrlThread.Destroy;
var
  CTIdx : Integer;
begin

  CS.Enter;
  try
    CTIdx := CtrlThreadList.IndexOf( Self );
    if
      ( CTIdx >= 0 )
    then
      CtrlThreadList.Delete( CTIdx );
  finally
    CS.Leave;
  end;

  inherited;
end;

initialization

  CS := TCriticalSection.Create;
  CS.Enter;
  try
    CtrlThreadList := TObjectList.Create;
    CtrlThreadList.OwnsObjects := False;
  finally
    CS.Leave;
  end;

finalization

  KillAllThreads;

  CS.Enter;
  try
    CtrlThreadList.Free;
  finally
    CS.Leave;
    try
      CS.Free;
    except
    end;
  end;

end.
Kaum macht man's richtig - schon funktioniert's
Zertifikat: Sir Rufo (Fingerprint: ‎ea 0a 4c 14 0d b6 3a a4 c1 c5 b9 dc 90 9d f0 e9 de 13 da 60)
  Mit Zitat antworten Zitat
alzaimar
(Moderator)

Registriert seit: 6. Mai 2005
Ort: Berlin
4.956 Beiträge
 
Delphi 2007 Enterprise
 
#9

Re: Threads "korrekt" beenden

  Alt 31. Jan 2009, 08:27
Solange der Finalization-Abschnitt immer VOR dem der Unit 'Classes' abgearbeitet wird, ist die Welt in Ordnung. Da viele Threads aber auch von anderen Units/Subsystemen abhängen, ist mir persönlich das nicht sicher genug. Wenn Du den Finalization-Code jedoch in einer exportierten Prozedur kapselst, kann der Anwender selbst bestimmen, wann die Threadliste aufgeräumt wird. Dann würde das doch richtig gut passen. Und wenn der Anwender vergisst, aufzuräumen, dann macht das eben dein Code... So etwa:
Delphi-Quellcode:
Unit CtrlThread;
...
Prozedure TerminateThreadList;
implementation
...
Procedure TerminateThreadList;
Begin
  If Not Assigned (CtrlThreadList) Then Exit;
  KillAllThreads;
  CS.Enter;
  try
    FreeAndNil(CtrlThreadList);
  finally
    CS.Leave;
    try
      CS.Free;
    except
    end;
  end;
end;

finalization
  TerminateThreadList;
end.
"Wenn ist das Nunstruck git und Slotermeyer? Ja! Beiherhund das Oder die Flipperwaldt gersput!"
(Monty Python "Joke Warefare")
  Mit Zitat antworten Zitat
Benutzerbild von Sir Rufo
Sir Rufo

Registriert seit: 5. Jan 2005
Ort: Stadthagen
9.454 Beiträge
 
Delphi 10 Seattle Enterprise
 
#10

Re: Threads "korrekt" beenden

  Alt 31. Jan 2009, 10:23
Der Einwand ist berechtigt und darum habe ich die KillAllThreads jetzt als class procedure definiert. So kann man aufräumen wann man will, muss aber nicht ...
Delphi-Quellcode:
unit CtrlThread;

interface

uses
  Classes;

type
  TCtrlThread = class( TThread )
  public
    class procedure KillAllThreads;
    constructor Create(CreateSuspended: Boolean);
    destructor Destroy; override;
  end;



implementation

uses
  Contnrs,
  SyncObjs;

var
  CtrlThreadList : TObjectList;
  CS : TCriticalSection;

{ TCtrlThread }

class procedure TCtrlThread.KillAllCtrlThreads;
var
  CTIdx : Integer;
begin
  while
    ( CtrlThreadList.Count > 0 )
  do
    begin

      CS.Enter;
      try

        for
          CTIdx := 0
        to
          CtrlThreadList.Count - 1
        do
          begin
            TCtrlThread( CtrlThreadList.Items[ CTIdx ] ).FreeOnTerminate := True;
            TCtrlThread( CtrlThreadList.Items[ CTIdx ] ).Terminate;
          end;

      finally
        CS.Leave;
      end;

    end;
end;

constructor TCtrlThread.Create(CreateSuspended: Boolean);
begin
  inherited Create( CreateSuspended );

  CS.Enter;
  try
    CtrlThreadList.Add( Self );
  finally
    CS.Leave;
  end;
end;

destructor TCtrlThread.Destroy;
var
  CTIdx : Integer;
begin

  CS.Enter;
  try
    CTIdx := CtrlThreadList.IndexOf( Self );
    if
      ( CTIdx >= 0 )
    then
      CtrlThreadList.Delete( CTIdx );
  finally
    CS.Leave;
  end;

  inherited;
end;

initialization

  CS := TCriticalSection.Create;
  CS.Enter;
  try
    CtrlThreadList := TObjectList.Create;
    CtrlThreadList.OwnsObjects := False;
  finally
    CS.Leave;
  end;

finalization

  TCtrlThread.KillAllThreads;

  CS.Enter;
  try
    CtrlThreadList.Free;
  finally
    CS.Leave;
    try
      CS.Free;
    except
    end;
  end;

end.
Kaum macht man's richtig - schon funktioniert's
Zertifikat: Sir Rufo (Fingerprint: ‎ea 0a 4c 14 0d b6 3a a4 c1 c5 b9 dc 90 9d f0 e9 de 13 da 60)
  Mit Zitat antworten Zitat
Antwort Antwort
Seite 1 von 2  1 2      


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 00:17 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