AGB  ·  Datenschutz  ·  Impressum  







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

Thread nicht terminiert?

Ein Thema von mcinternet · begonnen am 1. Feb 2013 · letzter Beitrag vom 1. Feb 2013
Antwort Antwort
mcinternet

Registriert seit: 22. Apr 2010
Ort: Odenwald
193 Beiträge
 
Delphi 10.3 Rio
 
#1

Thread nicht terminiert?

  Alt 1. Feb 2013, 10:45
Delphi-Version: XE2
Hallo,

Umgebung: Rad Studio XE3 Update 2

Ich habe einen Thread (MThread), der während beim Click auf einen Button erzeugt wird. Mit Option freeonterminate=true
Ein Ereignis onThreadTerminate wird zugewiesen.
Nach Auslösen dieses Ereignisses wird einiges abgearbeitet - klappt auch alles soweit.
Nur ein merkwürdiges Phänomen tritt auf: Wenn ich irgendwann später MThread.terminated abfrage, so ist dieser immer noch aktiv. - Es stört nicht wirklich. Auch ein erneutes Erzeugen und Starten klappt problemlos.
Mache ich allerdings beim FormClose die Zeile: if assigned(MThread) then freeandnil(MThread) rein, knallt es.

(Stört Euch nicht an der Formvariable oder so - ich arbeite hier mit einem multiple Docked-Forms Konzept,
wo alle FRMs im Prinzip nur Muster sind und die Childforms dynamisch erzeugt werden - somit kann jede FRM
mit eindeutigem Namen versehen werden und ich nutze da auch verschiedene Muster)

Meine Problematik dreht sich nur um diesen MThread

Hier mal ein wenig Code:

Delphi-Quellcode:
type
  TFrmGMaps = class(TChildform)
    WebGMaps1: TWebGMaps;
    starttimer: TTimer;
    .
    .
    . weitere Definitionen ...
    private
    { Private-Deklarationen }
  public
    { Public-Deklarationen }
  end;


  TMyThread = class(TThread)
     procedure execute; override;
  end;

 var

  threadaktiv : Boolean = False;
  MThread : TMyThread;
 
  // Form2 - Formvariable verworfen, wird bei Aufruf vergeben (Mutliple Forms)


implementation

{$R *.dfm}

uses main, childformverwaltung, System.StrUtils, UDM;

procedure TFrmGMaps.threadabschluss;
  var idx : integer;
  lat : string;
    lng : string;
    buwID : string;
    KName : string;
begin
  if not threadaktiv then begin
    threadtimer.Enabled := false;
    pan_warten.Visible := false;
    setstartmarker;
    for idx := 0 to Length(threadkname)-1 do begin
      lat := threadlat[idx];
      lng := threadlng[idx];
      KName := threadKName[idx];
      if ((lat<>'') and (lng<>'')) then WebGMaps1.Markers.Add(strtofloat(lat),strtofloat(lng),
                           ID+' '+KName,geticon(99, False),
                           True,True,True,False,false,idx);


    end;
    SetLength(threadlat,0);
    SetLength(threadlng,0);
    SetLength(threadkname,0);
    pan_gmapsteuerung.Visible := True;
  end;
end;

procedure TMyThread.Execute;
  var idx : integer;
   dynform : TFrmGMaps;

// GETCUMLIST_DIST_FROM ist ne ORacle Stored Proc

begin
 
    SetLength(threadlat,0);
    SetLength(threadlng,0);
    SetLength(threadkname,0);
    dynform := TFrmGMaps(Application.FindComponent(FrmMain.GmapThreadname));
    dynform.GETCUMLIST_DIST_FROM.execute;
    if dynform.GETCUMLIST_DIST_FROM.ParamByName('RESULT').Asinteger=DM.pkgCodes.VariableByName('INF_SUCCESS').AsInteger then
    begin
        idx := 0;
        dynform.JvGradientProgressBar1.Max := dynform.GETCUMLIST_DIST_FROM.RecordCount;
        SetLength(threadlat,dynform.GETCUMLIST_DIST_FROM.RecordCount);
        SetLength(threadlng,dynform.GETCUMLIST_DIST_FROM.RecordCount);
        SetLength(threadkname,dynform.GETCUMLIST_DIST_FROM.RecordCount);

        while (not dynform.GETCUMLIST_DIST_FROM.eof) do begin
          Synchronize(dynform.JvGradientProgressBar1.StepIt);
          inc(idx);
          if not ((dynform.GETCUMLIST_DIST_FROMCUM_DBLGEOLAT.AsString = dynform.gmaps_lat) // Um auszuschließen, das der Startmarker
             and ( dynform.GETCUMLIST_DIST_FROMCUM_DBLGEOLNG.AsString = dynform.gmaps_lng)) // überschrieben wird
          then begin
            SetLength(threadlat,idx);
            SetLength(threadlng,idx);
            SetLength(threadkname,idx);
            threadlat[idx-1] := dynform.GETCUMLIST_DIST_FROMCUM_DBLGEOLAT.AsString;
            threadlng[idx-1] := dynform.GETCUMLIST_DIST_FROMCUM_DBLGEOLNG.AsString;
            threadkname[idx-1] := dynform.GETCUMLIST_DIST_FROMCUM_STRNAME.AsString;
          end;
        dynform.GETCUMLIST_DIST_FROM.Next;
      end;
      dynform.GETCUMLIST_DIST_FROM.Close;
    end
    else
    begin
      //Fehler
    end;
end;

procedure TFrmGMaps.btn_querystartClick(Sender: TObject);
  var lat : string;
    lng : string;
    KName : string;
    idx : integer;
begin
  WebGMaps1.DeleteAllMapMarker;
  FrmMain.GmapThreadname := Self.Name;
  JvGradientProgressBar1.Position := 1;
  pan_warten.Left := Integer(Trunc((Self.Width - pan_warten.Width) / 2));
  pan_warten.Top := Integer(Trunc((Self.Height - pan_warten.Height) / 2));
  pan_warten.Visible := True;
  Application.ProcessMessages;
  MThread := TMyThread.Create(True);
  MThread.FreeOnTerminate := True;
  threadaktiv := true;
  MThread.OnTerminate := threadend;
  pan_gmapsteuerung.Visible := false;
  MThread.Resume;
end;

procedure TFrmGMaps.threadend(Sender: TObject);
begin
  threadaktiv := false;
  threadabschluss;
end;
irgendwo - irgendwann muss der Thread ja "zerstört" werden?

Gruss

MC
Jörg
  Mit Zitat antworten Zitat
CCRDude

Registriert seit: 9. Jun 2011
678 Beiträge
 
FreePascal / Lazarus
 
#2

AW: Thread nicht terminiert?

  Alt 1. Feb 2013, 11:06
Mit Option freeonterminate=true
[...]
Wenn ich irgendwann später MThread.terminated abfrage, so ist dieser immer noch aktiv.
[...]
Mache ich allerdings beim FormClose die Zeile: if assigned(MThread) then freeandnil(MThread) rein, knallt es.
FreeOnTerminate bedeutet nicht, dass alle Variablen, die diesen Thread referenzieren, auf nil gesetzt werden.

Somit greift die Abfrage auf MThread.Terminated evtl. auf ein nicht mehr existierendes Objekt zu - Fehler!

Und im FormClose ist MThread auch dann noch Assigned, wenn der Thread selber freigegeben ist, gleiches Problem!

Vllt. solltest Du MThread im OnTerminated auf nil setzen, bzw. das Konzept weiter überdenken.
  Mit Zitat antworten Zitat
mcinternet

Registriert seit: 22. Apr 2010
Ort: Odenwald
193 Beiträge
 
Delphi 10.3 Rio
 
#3

AW: Thread nicht terminiert?

  Alt 1. Feb 2013, 11:37
Mit Option freeonterminate=true
[...]
Wenn ich irgendwann später MThread.terminated abfrage, so ist dieser immer noch aktiv.
[...]
Mache ich allerdings beim FormClose die Zeile: if assigned(MThread) then freeandnil(MThread) rein, knallt es.
FreeOnTerminate bedeutet nicht, dass alle Variablen, die diesen Thread referenzieren, auf nil gesetzt werden.

Somit greift die Abfrage auf MThread.Terminated evtl. auf ein nicht mehr existierendes Objekt zu - Fehler!

Und im FormClose ist MThread auch dann noch Assigned, wenn der Thread selber freigegeben ist, gleiches Problem!

Vllt. solltest Du MThread im OnTerminated auf nil setzen, bzw. das Konzept weiter überdenken.

Die Procedure onterminate wird nur einmal aufgerufen. Das ist nicht das Problem. Möchte nur das der Thread gekillt wird. Wo kann ich das am Besten machen? Und womit? Freeandnil? Oder destroy?

Gruss
Jörg
  Mit Zitat antworten Zitat
Klaus01

Registriert seit: 30. Nov 2005
Ort: München
5.777 Beiträge
 
Delphi 10.4 Sydney
 
#4

AW: Thread nicht terminiert?

  Alt 1. Feb 2013, 11:40
.. wenn der Thread mit freeOnTerminate gestartet wurde
und im laufenden Thread ann die Execute Methode verlassen wird,
dann ist er terminiert - nicht nil aber beendet.

Das sollte auch im TaskManager verfolgbar sein.

Grüße
Klaus
Klaus
  Mit Zitat antworten Zitat
mcinternet

Registriert seit: 22. Apr 2010
Ort: Odenwald
193 Beiträge
 
Delphi 10.3 Rio
 
#5

AW: Thread nicht terminiert?

  Alt 1. Feb 2013, 11:54
.. wenn der Thread mit freeOnTerminate gestartet wurde
und im laufenden Thread ann die Execute Methode verlassen wird,
dann ist er terminiert - nicht nil aber beendet.

Das sollte auch im TaskManager verfolgbar sein.

Grüße
Klaus
Wie kann ich das nun am elegantesten lösen, das das Ding auch gekillt wird?

im OnTerminate ein free... oder destroy?

Gruss
Jörg
Jörg
  Mit Zitat antworten Zitat
sahimba

Registriert seit: 14. Nov 2011
Ort: Berlin, Hauptstadt der DDR
137 Beiträge
 
Delphi 10 Seattle Professional
 
#6

AW: Thread nicht terminiert?

  Alt 1. Feb 2013, 12:07
Was willst Du denn noch "killen" bei FreeOnTerminate = True, wenn der Thread seine Execute-Methode beendet hat? Er ist dann terminiert und wird automagisch freigegeben.
  Mit Zitat antworten Zitat
Benutzerbild von sx2008
sx2008

Registriert seit: 16. Feb 2008
Ort: Baden-Württemberg
2.332 Beiträge
 
Delphi 2007 Professional
 
#7

AW: Thread nicht terminiert?

  Alt 1. Feb 2013, 12:59
Von hinten durch die Brust ins Auge:
Delphi-Quellcode:
procedure TMyThread.Execute;
var
   dynform : TFrmGMaps;
begin
  dynform := TFrmGMaps(Application.FindComponent(FrmMain.GmapThreadname));
  // ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Der Thread braucht offensichtlich ein TFrmGMaps-Objekt für seine Arbeit.
Dann wäre es sehr sinnvoll, wenn man dem Thread dieses Objekt von Aussen geben würde.
Dadurch, dass der Thread sich diese Info selbst besorgen muss, entsteht ein Kuddelmuddel.
Der Thread braucht und soll die Objekte "Application" und "FrmMain" nicht kennen.
Delphi-Quellcode:
TMyThread = class(TThread)
public
   dynform : TFrmGMaps; // NEU <====
   procedure execute; override;
end;

procedure TFrmGMaps.btn_querystartClick(Sender: TObject);
...
begin
...
// und Erzeugen sieht dann so aus
  MThread := TMyThread.Create(True);
  MThread.FreeOnTerminate := True;
  MThread.OnTerminate := threadend;
  MThread.dynform := self; // <===

Geändert von sx2008 ( 1. Feb 2013 um 19:33 Uhr)
  Mit Zitat antworten Zitat
Antwort Antwort


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 09:53 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