Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   GUI-Design mit VCL / FireMonkey / Common Controls (https://www.delphipraxis.net/18-gui-design-mit-vcl-firemonkey-common-controls/)
-   -   Thread aus Tobjectlist beenden (https://www.delphipraxis.net/180889-thread-aus-tobjectlist-beenden.html)

youuu 27. Jun 2014 22:55

Thread aus Tobjectlist beenden
 
Hi,

im FormCloseQuery frage ich meine Objectlist ab, on moch Thread vorhanden sind und wenn ja sollen diese sofort beendet werden.

Delphi-Quellcode:
  if FThread_liste.Count <> 0 then Begin
    for i := 0 to FThread_liste.Count -1 do begin
      if Assigned((FThread_liste.Items[i] as TThread)) then
        (FThread_liste.Items[i] as TThread).Terminate;
    end;
  End;
Allerdings alufen die Threads einfach munter weiter.

Uwe Raabe 27. Jun 2014 23:11

AW: Thread aus Tobjectlist beenden
 
Fragen die Threads denn regelmäßig ab, ob sie Terminated wurden? (und beenden sich dann auch!)

youuu 27. Jun 2014 23:14

AW: Thread aus Tobjectlist beenden
 
Delphi-Quellcode:
while not (FThread_liste.Items[i] as TThread).Terminated do
  Delay(200);
[dcc32 Fehler] Form_Main.pas(1662): E2362 Auf protected-Symbol TThread.Terminated kann nicht zugegriffen werden

Hm

Sir Rufo 27. Jun 2014 23:19

AW: Thread aus Tobjectlist beenden
 
Den Code kann man auch so schreiben
Delphi-Quellcode:
// OwnsObjects sollte True sein
FThread_liste.Clear;
Zitat:

Zitat von youuu (Beitrag 1263670)
Delphi-Quellcode:
while not (FThread_liste.Items[i] as TThread).Terminated do
  Delay(200);
[dcc32 Fehler] Form_Main.pas(1662): E2362 Auf protected-Symbol TThread.Terminated kann nicht zugegriffen werden

Hm

Die Threads und nicht die Thread-Liste sollen ja auch das Terminated auswerten.
Der Code zeigt allerdings auch, dass du das eben nicht machst, da du augenscheinlich nicht weißt, wo und wozu man das benutzt.
Delphi-Quellcode:
procedure TMyThread.Execute;
begin
  inherited;
  while not Terminted do
  begin
    // tue was hier immer wieder ohne Unterlass, ok bis eben Terminated
  end;
end;

youuu 27. Jun 2014 23:20

AW: Thread aus Tobjectlist beenden
 
Sir Rufo, das versteh ich nun nicht so ganz, was hat das damit zu tun das der Thread beendet werden soll?
Oder gibt die Liste dann die Threads automatisch frei?

Edit: hab ich eben ausprobiert, thread abeit dennoch weiter.

Sir Rufo 27. Jun 2014 23:27

AW: Thread aus Tobjectlist beenden
 
Zitat:

Zitat von youuu (Beitrag 1263672)
Sir Rufo, das versteh ich nun nicht so ganz, was hat das damit zu tun das der Thread beendet werden soll?
Oder gibt die Liste dann die Threads automatisch frei?

Edit: hab ich eben ausprobiert, thread abeit dennoch weiter.

Na logisch, wenn der Thread auch nicht selber schaut, ob er aufhören soll :roll:

Eine
Delphi-Quellcode:
TObjectList
mit Delphi-Referenz durchsuchenTObjectList.OwnsObjects auf
Delphi-Quellcode:
True
verwaltet die Instanzen des Inhaltes selber und bei
Delphi-Quellcode:
Clear
werden alle Instanzen (in der Liste) freigegeben.

Ein Thread wird im destructor beendet (Terminate) und die Instanz verschwindet im Nirwana ...

... wenn der Thread-Code auch wirklich aufhört

Sir Rufo 28. Jun 2014 00:13

AW: Thread aus Tobjectlist beenden
 
Zitat:

Zitat von youuu (Beitrag 1263667)
Delphi-Quellcode:
  if FThread_liste.Count <> 0 then Begin
    for i := 0 to FThread_liste.Count -1 do begin
      if Assigned((FThread_liste.Items[i] as TThread)) then
        (FThread_liste.Items[i] as TThread).Terminate;
    end;
  End;

Da der Code ja im Delphi-Referenz durchsuchenTForm.OnCloseQuery laufen soll, solltest du den wie folgt nehmen:
Delphi-Quellcode:
for i := 0 to FThread_liste.Count - 1 do
  if Assigned(FThread_list.Items[i]) and (FThread_list.Items[i] is TThread) then
    (FThread_liste.Items[i] as TThread).Terminate;
  1. Die Überprüfung
    Delphi-Quellcode:
    if FThread_liste.Count <> 0 then
    ist überflüssig, denn genau das passiert auch bei
    Delphi-Quellcode:
    for i := 0 to FThread_liste.Count - 1 do
  2. Triffst du bei
    Delphi-Quellcode:
    FThread_liste.Items[i] as TThread
    auf ein Element, das nicht von
    Delphi-Quellcode:
    TThread
    abgleitet wurde, dann bekommst du eine
    Delphi-Quellcode:
    Exception
    um die Ohren gehauen Delphi-Referenz durchsuchenEInvalidCast. Das
    Delphi-Quellcode:
    Assigned()
    drumherum hilft dir da auch nicht mehr.
Hier der Test
Delphi-Quellcode:
program dp_180889;

{$APPTYPE CONSOLE}
{$R *.res}

uses
  {System} SysUtils, Contnrs, Classes;

type
  TTestThread = class( TThread )
  protected
    procedure Execute; override;
  end;

  { TTestThread }

procedure TTestThread.Execute;
begin
  inherited;
  while not Terminated do
    begin
      Sleep( 50 ); // immer nur ein wenig schlafen, bis eben Terminated ...
    end;
end;

{$DEFINE UNSICHER}

procedure Test;
var
  LList : TObjectList;
  LIdx : Integer;
begin
  LList := TObjectList.Create( True );
  try

    LList.Add( TTestThread.Create( False ) );
    LList.Add( nil );
    LList.Add( TObject.Create ); // Eine einfache TObject-Instanz
    LList.Add( TTestThread.Create( False ) );
{$IFDEF UNSICHER}
    write( 'UNSICHER: ' );
{$ELSE}
    write( 'SICHER: ' );
{$ENDIF}
    for LIdx := 0 to LList.Count - 1 do
      begin
        write( LIdx, '...' );
{$IFDEF UNSICHER}
        if Assigned( LList.Items[LIdx] as TThread )
{$ELSE}
        if Assigned( LList.Items[LIdx] ) and ( LList.Items[LIdx] is TThread )
{$ENDIF}
        then
          // Threads mitteilen, dass sie sich beenden sollen
          ( LList.Items[LIdx] as TThread ).Terminate;
      end;

    Writeln( 'Fertig' );

    LList.Clear; // Wenn der Befehl durch ist, dann sind auch alle Threads beendet

  finally
    LList.Free;
  end;
end;

begin
  try
    Test;
  except
    on E : Exception do
      Writeln( E.ClassName, ': ', E.Message );
  end;
  Readln;

end.
und das Resultat
Code:
UNSICHER: 0...1...2...EInvalidCast: Ungültige Typumwandlung
SICHER: 0...1...2...3...Fertig

Dejan Vu 28. Jun 2014 08:35

AW: Thread aus Tobjectlist beenden
 
Wenn Du auf 'is' abfragst, kannst Du hart casten. Das Pattern
Delphi-Quellcode:
if (foo is TBar) then
  TBar(foo)....
// Ist genauso sicher wie(aber wesentlich schneller als)
if (foo is TBar) then
  (foo as TBar)....
Zusätzlich sollte man noch darauf hinweisen (auch wenn es eigentlich selbstverständlich ist), das ein Thread in seiner Execute-Methode 'immer mal wieder' auf 'Terminated' prüfen sollte, d.h. auch in inneren Schleifen. Die 'Terminate' Methode beendet den Thread nämlich überhaupt nicht, sondern setzt nur das Flag 'Terminated' auf True.

Die Methode sollte also besser heißen: 'TerminateRequest', oder auf deutsch: 'SachDenFredErSollSichMaBeendenAberErMussDasSchonA uchMerkenNe';

youuu 28. Jun 2014 09:40

AW: Thread aus Tobjectlist beenden
 
Ah ok, jetzt versteh ich es. Danke


Alle Zeitangaben in WEZ +1. Es ist jetzt 03:04 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