![]() |
AW: TTask/ITask + Synchronze + OnDestroy
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. |
AW: TTask/ITask + Synchronze + OnDestroy
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; |
AW: TTask/ITask + Synchronze + OnDestroy
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. |
AW: TTask/ITask + Synchronze + OnDestroy
Zitat:
|
AW: TTask/ITask + Synchronze + OnDestroy
Zitat:
Daher die Anforderung, zu warten, bis der Thread SICHER beendet ist. |
AW: TTask/ITask + Synchronze + OnDestroy
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.
|
AW: TTask/ITask + Synchronze + OnDestroy
Zitat:
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:
Da weiß ich gar nicht, wo ich da ansetzen soll.
while Button1.Enabled = false do begin
Application.ProcessMessages; end; 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. :twisted: |
AW: TTask/ITask + Synchronze + OnDestroy
Liste der Anhänge anzeigen (Anzahl: 1)
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...
|
AW: TTask/ITask + Synchronze + OnDestroy
Zitat:
Warum sollte hier ein Thread tauglicher sein als ein Task? |
AW: TTask/ITask + Synchronze + OnDestroy
Zitat:
|
Alle Zeitangaben in WEZ +1. Es ist jetzt 12:51 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-2025 by Thomas Breitkreuz