Autor Beitrag
nru
Hält's aus hier
Beiträge: 9
Erhaltene Danke: 1



BeitragVerfasst: Mo 18.10.10 15:31 
Nochmal ich zum Thema Thread, diesmal jedoch anders gelagert.

Ein Thread wird erzeugt und direkt gestartet, läuft jedoch durchaus etwas länger. Bei einem erneuten Aufruf der Funktion, die den Thread zuvor gestartet hat, wird dann also erst geprüft, ob der alte Thread vielleicht noch läuft. Abfrage einer Integer über eine class function. Läuft er, wird er terminiert anschl. WaitFor und alles wieder freigegeben (FreeAndNil() - erst dann neu gestartet.

Da er wie gesagt länger läuft wird er u.U. vom ProgrammEnde "überrascht" oder aber soll neu gestartet werden (neue Anforderung). Dann aber sollte es kein OnTerminate mehr geben, weil eine Aktualisierung der GUI des Hauptthreads nicht nötig ist. Deshalb möchte ich erreichen, dass ein OnTerminate auch tatsächlich nur dann ausgelöst wird, wenn der Thread "normal" - also nach Ablauf von Execute ohne Unterbrechung - beendet wurde! Gem. Standard-Verhalten von TThread würde OnTerminate-Event jedoch auch dann aufgerufen, wenn der Thread über .Free "beendet" würde. TThread.Free() bzw. .Destroy() termniniert und wartet auf Ende, ist also grundsätzlich ok, ruft aber OnTerminate auf - auch wenns wie in meinem Fall nicht sein soll.

Ich hab mir jetzt durch das überschreiben von DoTerminate geholfen.

ausblenden ThreadUnit
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
  TGPSGesamtThread = class(TThread)
  private
    FGesamt: Integer;
    FHTTP: TIdHTTP;
    FxmlDoc: TJvSimpleXML;
    FURL: String;
  protected
    procedure Execute; override;
  public
    constructor Create( url: String; callback: TNotifyEvent );
    class function IsRunning: boolean;
    procedure DoTerminate; override;        
    property Gesamt: Integer read FGesamt;
  end;

constructor TGPSGesamtThread.Create( url: string; callback: TNotifyEvent );
begin
  FURL := RemoveLimit(url);     // Limit wieder rausnehmen, damit hier Gesamtanzahl hochgezählt werden kann
  OnTerminate := callback;
  inherited Create( false );
end;

procedure TGPSGesamtThread.DoTerminate;
begin
  // Hier soll sichergestellt werden, dass der Event OnTerminate nicht mehr
  // ausgelöst wird, wenn der Thread termininiert (also abbruch von außen) wurde.
  // Normales Ende nach .Execute setzt Terminated _nicht_!
  if not Terminated then
    inherited DoTerminate;
end;



ausblenden HauptUnit
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
.
    if TGPSGesamtThread.IsRunning then 
       StopThread();
    FThrGesamt := TGPSGesamtThread.Create( FInternalURL, AfterFinishedGesamtThread );
.

procedure TGPSAPI.StopThread();
begin
  if Assigned( FThrGesamt ) then begin
    with FThrGesamt do begin
      Terminate;        {Thread beenden}
      WaitFor;          {Und reagieren lassen}
    end;
    FreeAndNil( FThrGesamt );
  end;
end;


War das verständlich oder totaler Bockmist?! :?
Das funktioniert soweit auch recht gut und eigentlich so, wie ich es gerne hätte ;)
Frage ist nur, ist das i.O. so ... oder doch eher von hinten durch die Brust ins Auge?!


Dank & Gruss
nru
bummi
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 1248
Erhaltene Danke: 187

XP - Server 2008R2
D2 - Delphi XE
BeitragVerfasst: Mo 18.10.10 15:41 
was wäre wenn Du wenn nicht mehr gewünscht
MyThread.OnTerminate := nil
verwendest?
nru Threadstarter
Hält's aus hier
Beiträge: 9
Erhaltene Danke: 1



BeitragVerfasst: Mo 18.10.10 16:08 
user profile iconbummi hat folgendes geschrieben Zum zitierten Posting springen:
was wäre wenn Du wenn nicht mehr gewünscht
MyThread.OnTerminate := nil
verwendest?


Klasse Tip! Nach entsprechender Erweiterung von .StopThread() und dem Austausch von FreeAndNil() gegen StopThread () im Destroy des Aufrufers gehts dann auch ohne Anpssung des Standard-Verhaltens von TThread.

Vielen Dank

Gruss
nru

ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
procedure TGPSAPI.StopThread();
begin
  if Assigned( FThrGesamt ) then begin
    with FThrGesamt do begin
      OnTerminate := nil;
      Terminate;        {Thread beenden}
      WaitFor;          {Und reagieren lassen}
    end;
    FreeAndNil( FThrGesamt );
  end;
end;