AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Zurück Delphi-PRAXiS Programmierung allgemein Programmieren allgemein TTask/ITask + Synchronze + OnDestroy

TTask/ITask + Synchronze + OnDestroy

Ein Thema von TigerLilly · begonnen am 7. Jan 2021 · letzter Beitrag vom 11. Jan 2021
Antwort Antwort
Seite 2 von 3     12 3   
TigerLilly

Registriert seit: 24. Mai 2017
Ort: Wien, Österreich
902 Beiträge
 
Delphi 10.3 Rio
 
#11

AW: TTask/ITask + Synchronze + OnDestroy

  Alt 8. Jan 2021, 08:01
Nein. Das Synchronize stellt ja eben sicher, dass der Button noch existiert. Wäre bei Thread.Queue anders.

Und ich möchte den Task ja canceln, da hilft wait nicht.
  Mit Zitat antworten Zitat
shebang

Registriert seit: 7. Feb 2020
37 Beiträge
 
Delphi 10.4 Sydney
 
#12

AW: TTask/ITask + Synchronze + OnDestroy

  Alt 8. Jan 2021, 09:13
Damit funktioniert es bei mir:
Delphi-Quellcode:
procedure TForm1.FormCloseQuery(Sender: TObject; var CanClose: Boolean);
begin
  if Assigned(fTask) then begin
    fTask.Cancel;
  end;
end;

procedure TForm1.Button1Click(Sender: TObject);
begin
  Button1.Enabled := false;
  Button1.Text := 'Task running';
  fTask := TTask.Run(procedure()
    begin
      repeat
        if TTask.CurrentTask.Status = TTaskStatus.Canceled then
          Exit; // Exit statt Break
        Sleep(10);
        TThread.Synchronize(nil, procedure()
        begin
          Button1.Text := DateTimeToStr(Now);
        end);
      until false;
      Sleep(100);
      TThread.Synchronize(nil, procedure()
      begin
        Button1.Enabled := true;// Diese beiden Zugriffe müssen
        Button1.Text := 'Start Task'; // auch synchronisiert werden
      end);
    end);
end;

Geändert von shebang ( 8. Jan 2021 um 09:29 Uhr)
  Mit Zitat antworten Zitat
TiGü

Registriert seit: 6. Apr 2011
Ort: Berlin
2.810 Beiträge
 
Delphi 10.2 Tokyo Enterprise
 
#13

AW: TTask/ITask + Synchronze + OnDestroy

  Alt 8. Jan 2021, 10:06
Ich habe mir das mal umformatiert mit TProc und TThreadProcedure Variablen, weil ich diese durchaus valide Schreibweise mit den geschachtelten anonymen Funktionen nicht so mag.
Nach dem FormDestroy ist das Formular und seine Komponenten schon weg. Daher die Prüfung mit Assigned(Button1), ob der Button überhaupt noch valide da ist.

Delphi-Quellcode:
unit Unit2;

interface

uses
  System.SysUtils, System.Types, System.UITypes, System.Classes, System.Variants,
  FMX.Types, FMX.Controls, FMX.Forms, FMX.Graphics, FMX.Dialogs, FMX.Controls.Presentation, FMX.StdCtrls,
  System.Threading;

type
  TForm1 = class(TForm)
    Button1: TButton;
    Button2: TButton;
    procedure FormDestroy(Sender: TObject);
    procedure Button1Click(Sender: TObject);
    procedure Button2Click(Sender: TObject);
  private
    fTask: ITask;
    procedure DoCancelTask;
  end;

var
  Form1: TForm1;

implementation

{$R *.fmx}

procedure TForm1.FormDestroy(Sender: TObject);
begin
  DoCancelTask;
end;

procedure TForm1.Button1Click(Sender: TObject);
var
  MainTaskProc: TProc;
begin
  Button1.Enabled := false;
  Button1.Text := 'Task running';

  MainTaskProc := procedure()
    var
      UpdateDateTime: TThreadProcedure;
      ReactivateButton: TThreadProcedure;
    begin
      UpdateDateTime := procedure()
        begin
          if Assigned(Button1) then
          begin
            Button1.Text := DateTimeToStr(Now);
          end;
        end;

      ReactivateButton := procedure()
        begin
          if Assigned(Button1) then
          begin
            Button1.Enabled := true;
            Button1.Text := 'Start Task';
          end;
        end;

      repeat
        if TTask.CurrentTask.Status = TTaskStatus.Canceled then
        begin
          Break;
        end;
        Sleep(10);
        TThread.Synchronize(nil, UpdateDateTime);
      until false;

      Sleep(100);

      TThread.Synchronize(nil, ReactivateButton);
    end;

  fTask := TTask.Run(MainTaskProc);
end;

procedure TForm1.Button2Click(Sender: TObject);
begin
  DoCancelTask;
end;

procedure TForm1.DoCancelTask;
begin
  if Assigned(fTask) then
  begin
    fTask.Cancel;
  end;
end;

end.
  Mit Zitat antworten Zitat
Benutzerbild von Uwe Raabe
Uwe Raabe

Registriert seit: 20. Jan 2006
Ort: Lübbecke
8.656 Beiträge
 
Delphi 10.4 Sydney
 
#14

AW: TTask/ITask + Synchronze + OnDestroy

  Alt 8. Jan 2021, 10:29
Nach dem FormDestroy ist das Formular und seine Komponenten schon weg. Daher die Prüfung mit Assigned(Button1), ob der Button überhaupt noch valide da ist.
Wenn das Form und seine Komponenten schon weg sind (ich vermute, das heißt freigegeben), dann kann Assigned(Button1) immer noch True liefern, obwohl der Zugriff darauf dann auf undefiniertem Speicher erfolgt. Das kann dann gut gehen - muss aber nicht.
Uwe Raabe
Certified Delphi Master Developer
Embarcadero MVP
Blog: The Art of Delphi Programming
  Mit Zitat antworten Zitat
TigerLilly

Registriert seit: 24. Mai 2017
Ort: Wien, Österreich
902 Beiträge
 
Delphi 10.3 Rio
 
#15

AW: TTask/ITask + Synchronze + OnDestroy

  Alt 8. Jan 2021, 10:44
Damit funktioniert es bei mir:
Delphi-Quellcode:
procedure TForm1.FormCloseQuery(Sender: TObject; var CanClose: Boolean);
begin
  if Assigned(fTask) then begin
    fTask.Cancel;
  end;
end;
Nein, das funktioniert nur, wenn der Task schnell genug beendet. Wenn das länger dauert, wird das Formular geschlossen und der TAsk läuft noch - weil er mit Beenden noch nicht fertig ist.

Daher die Anforderung, zu warten, bis der Thread SICHER beendet ist.
  Mit Zitat antworten Zitat
shebang

Registriert seit: 7. Feb 2020
37 Beiträge
 
Delphi 10.4 Sydney
 
#16

AW: TTask/ITask + Synchronze + OnDestroy

  Alt 8. Jan 2021, 11:33
Dann wäre die Frage, ob ein Task für deine aktuelle Aufgabe geeignet ist. Wenn ich mir die verfügbaren Methoden von TTask so anschaue, dann sieht es für mich eher so aus, dass Tasks für kurze kleine Aufgaben gedacht sind, auf deren Erfüllung man wartet. Dein Beispiel enthält ja eine Schleife, die abgebrochen werden muss, es gibt kein reguläres Ende. Ich würde an dieser Stelle wohl eher einen Thread nehmen.

Geändert von shebang ( 8. Jan 2021 um 11:37 Uhr)
  Mit Zitat antworten Zitat
TiGü

Registriert seit: 6. Apr 2011
Ort: Berlin
2.810 Beiträge
 
Delphi 10.2 Tokyo Enterprise
 
#17

AW: TTask/ITask + Synchronze + OnDestroy

  Alt 8. Jan 2021, 11:40
Nach dem FormDestroy ist das Formular und seine Komponenten schon weg. Daher die Prüfung mit Assigned(Button1), ob der Button überhaupt noch valide da ist.
Wenn das Form und seine Komponenten schon weg sind (ich vermute, das heißt freigegeben), dann kann Assigned(Button1) immer noch True liefern, obwohl der Zugriff darauf dann auf undefiniertem Speicher erfolgt. Das kann dann gut gehen - muss aber nicht.
Vollkommen richtig.
Zumindest hat das jetzt dreimal anhand dieses Minimalbeispiels funktioniert.
Meine Hand würde ich dafür aber nicht ins Feuer legen.

Zumindest ist das besser als das Rumgehampel mit
Delphi-Quellcode:
while Button1.Enabled = false do begin
     Application.ProcessMessages;
end;
Da weiß ich gar nicht, wo ich da ansetzen soll.

Je nach echter Anforderung würde ich ggf. den Schreib-Overhead mit einem echten TThread-Abkömmling vorschlagen, da man dann die volle Kontrolle hat und gescheit mit einem TEvent warten kann.

Übrigens wundere ich mich, dass noch keiner gemeckert hat, weil im Ursprungspost einfach mal hart im externen Threadkontext auf Eigenschaften der GUI-Komponenten zugegriffen wird (Button.Enabled/Text).
Das steht zwar alles visuell in der TForm1.Button1Click, läuft aber sozusagen im Execute eines externen Threads.
Da wurden andere sonst immer virtuell an den Ohren gezogen.

Geändert von TiGü ( 8. Jan 2021 um 12:23 Uhr)
  Mit Zitat antworten Zitat
Benutzerbild von Uwe Raabe
Uwe Raabe

Registriert seit: 20. Jan 2006
Ort: Lübbecke
8.656 Beiträge
 
Delphi 10.4 Sydney
 
#18

AW: TTask/ITask + Synchronze + OnDestroy

  Alt 8. Jan 2021, 13:01
Ich weiß ja nicht, ob das für den realen Anwendungsfall passt, aber in solchen Fällen verwende ich dann ein Zwischenobjekt. Ich hab da mal was vorbereitet...
Angehängte Dateien
Dateityp: zip TaskProjekt.zip (1,6 KB, 7x aufgerufen)
Uwe Raabe
Certified Delphi Master Developer
Embarcadero MVP
Blog: The Art of Delphi Programming
  Mit Zitat antworten Zitat
TigerLilly

Registriert seit: 24. Mai 2017
Ort: Wien, Österreich
902 Beiträge
 
Delphi 10.3 Rio
 
#19

AW: TTask/ITask + Synchronze + OnDestroy

  Alt 8. Jan 2021, 13:03
Dann wäre die Frage, ob ein Task für deine aktuelle Aufgabe geeignet ist. Wenn ich mir die verfügbaren Methoden von TTask so anschaue, dann sieht es für mich eher so aus, dass Tasks für kurze kleine Aufgaben gedacht sind, auf deren Erfüllung man wartet. Dein Beispiel enthält ja eine Schleife, die abgebrochen werden muss, es gibt kein reguläres Ende. Ich würde an dieser Stelle wohl eher einen Thread nehmen.
Das erschließt sich mir nicht. TTask kapselt doch nur den Zugriff auf Threads. Die Endlos-Schleife samt Abbruch ist nur zu Testzwecken, ändert an der Aufgabenstellung nichts. In echt beendet der Task natürlich, wenn man ihn lässt.

Warum sollte hier ein Thread tauglicher sein als ein Task?
  Mit Zitat antworten Zitat
TigerLilly

Registriert seit: 24. Mai 2017
Ort: Wien, Österreich
902 Beiträge
 
Delphi 10.3 Rio
 
#20

AW: TTask/ITask + Synchronze + OnDestroy

  Alt 8. Jan 2021, 13:07
Je nach echter Anforderung würde ich ggf. den Schreib-Overhead mit einem echten TThread-Abkömmling vorschlagen, da man dann die volle Kontrolle hat und gescheit mit einem TEvent warten kann.
Nochmal. Ich möchte das Fenster schliueßen + allfällige Tasks dabei beenden. Nur dann(!!) habe ich ein Problem. Das "warten" ist ja leicht gesagt - aber wie ist die Frage. Zeig mir was besseres als mein Rumgehample.
  Mit Zitat antworten Zitat
Themen-Optionen Thema durchsuchen
Thema durchsuchen:

Erweiterte Suche
Ansicht

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 +2. Es ist jetzt 03:56 Uhr.
Powered by vBulletin® Copyright ©2000 - 2021, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2021 by Daniel R. Wolf