Delphi-PRAXiS
Seite 3 von 3     123   

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Programmieren allgemein (https://www.delphipraxis.net/40-programmieren-allgemein/)
-   -   TTask/ITask + Synchronze + OnDestroy (https://www.delphipraxis.net/206572-ttask-itask-synchronze-ondestroy.html)

TigerLilly 8. Jan 2021 12:16

AW: TTask/ITask + Synchronze + OnDestroy
 
Zitat:

Zitat von Uwe Raabe (Beitrag 1480568)
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...

Danke dafür. Aber wenn ich den Task starte und das Fenster schließe, gibt es eine Zugriffsverletzung.Übersehe ich was?

Die Zugriffsverletzung sieht man aber nur im Debugger und nur wenn dias Unterbrechen bei Exceptions eingeschalten ist. Zur Laufzeit wird die Exception nicht angezeigt.

Gilt auch für TiGüs Vorschlag mit OnCloseQuery. Wahrscheinlich wird die Excpetion geworfen, wenn das ganze Exceptionhandling schon abgebaut ist.

Uwe Raabe 8. Jan 2021 12:30

AW: TTask/ITask + Synchronze + OnDestroy
 
Nein, aber ich. Wenn das Form freigegeben wird, dann auch die Wrapper-Instanz - auch wenn die Task noch nicht fertig ist. In meinen Anwendungsfällen hält die Task indirekt selbst noch ein anderes Interface auf den Wrapper, aber dabei geht es auch um eine ganz andere Anforderung.

Multi-Threading bleibt halt schwierig...

TigerLilly 8. Jan 2021 12:38

AW: TTask/ITask + Synchronze + OnDestroy
 
Zitat:

Zitat von Uwe Raabe (Beitrag 1480576)
Multi-Threading bleibt halt schwierig...

Ha! Und ich hab gedacht, ich bin unfähig. Danke trotzdem!

Uwe Raabe 8. Jan 2021 12:51

AW: TTask/ITask + Synchronze + OnDestroy
 
Liste der Anhänge anzeigen (Anzahl: 1)
Neuer Versuch, der sich mehr an meinem (bislang jedenfalls funktionierenden) Code orientiert.
Ich vermute, das eigentliche Problem ist das Halten des ITask-Interfaces, was ich in meinem Code eigentlich nie mache.

shebang 8. Jan 2021 13:24

AW: TTask/ITask + Synchronze + OnDestroy
 
Zitat:

Zitat von TigerLilly (Beitrag 1480570)
Warum sollte hier ein Thread tauglicher sein als ein Task?

Einem Thread kann ich (über Terminate) mitteilen, dass er sich beenden soll und dann darauf warten, bis er sich selbst beendet hat. Bei einem Task scheint das nicht vorgesehen zu sein.

Uwe Raabe 8. Jan 2021 14:28

AW: TTask/ITask + Synchronze + OnDestroy
 
Zitat:

Zitat von shebang (Beitrag 1480581)
Einem Thread kann ich (über Terminate) mitteilen, dass er sich beenden soll und dann darauf warten, bis er sich selbst beendet hat. Bei einem Task scheint das nicht vorgesehen zu sein.

Das geht mit ITask auch. Problematisch ist hier nur der Synchronize-Aufruf im Task-Thread, der mit dem Wait im Hauptthread zu einem Deadlock führt. Ohne geeignete Maßnahmen wäre das mit einem TThread auch so.

shebang 8. Jan 2021 15:41

AW: TTask/ITask + Synchronze + OnDestroy
 
Zitat:

Zitat von Uwe Raabe (Beitrag 1480595)
Problematisch ist hier nur der Synchronize-Aufruf im Task-Thread, der mit dem Wait im Hauptthread zu einem Deadlock führt. Ohne geeignete Maßnahmen wäre das mit einem TThread auch so.

Stimmt, der Task müsste selbst unterscheiden, ob er durch den Button oder über das Schließen der Form beendet wurde. Nur im ersten Fall ist eine weitere Synchronisation notwendig.

TigerLilly 8. Jan 2021 15:57

AW: TTask/ITask + Synchronze + OnDestroy
 
Mit einem Timer geht es:

Code:
procedure TForm1.FormCloseQuery(Sender: TObject; var CanClose: Boolean);
begin
  CanClose := true;
  if Assigned(fTask) then begin
    if fTask.Status = TTaskStatus.Running then
      fTask.Cancel;
    Timer1.Enabled := true;
    CanClose:=Button1.Enabled;
  end;
end;

procedure TForm1.Timer1Timer(Sender: TObject);
begin
  if Button1.Enabled then
    Close;
end;
Wenn das Formular geschlossen werden soll, wird der Task gecancelt. Ist der Task aber nocht fertig beendet, wird das Schließen unterbunden + statt dessen ein Timer gestartet, der 1x/sec nachschaut, ob der Task jetzt endlich fertig ist. Wenn ja, wird das Formular geschlossen.

Besser?

TigerLilly 11. Jan 2021 07:46

AW: TTask/ITask + Synchronze + OnDestroy
 
Liste der Anhänge anzeigen (Anzahl: 1)
Uwe hat mich auf die Idee eines Wrappers gebracht, in den man diesen Overhead verpacken kann. Dann schaut das Beenden - mit Warten bis der Task fertig abgebrochen ist, so aus:
Code:
procedure TvTaskWrapper.FormClose(Sender: TObject; var Action: TCloseAction);
begin
  Action := aTaskWrapper.CancelTaskWithWait;
end;
Und das tut nicht viel mehr, als zu schauen, ob der Task fertig ist, wenn nicht wird ein Timer gestertet und das Schließen unterbunden. Der Timmer versucht dann immer wieder, das Close aufzurufen + das Spiel beginnt von vorn:
Code:
function TTaskWrapper.CancelTaskWithWait: TCloseAction;
begin
  if isActive then begin
    CancelTask;
    fTimer.Enabled := true;
    Result := TCloseAction.caNone;
  end else begin
    Result := TCloseAction.caFree;
  end;
end;
Auch das Syncen mit dem UI-Thread und einen Status, damit man weiß, wann der Thread fertig ist, kann man reinpacken:
Code:
type
  TTaskWrapper = class
  private
    fTimer: TTimer;
    fTask: ITask;
    fForm: Tform;
    fisActive: Boolean;
    procedure fOnTimer(Sender: TObject);
    function ShouldStop: Boolean;
  public
    constructor create(aForm: Tform; aProc: TProc);
    destructor Destroy;
    procedure DoSynchronized(aProc: TProc);
    procedure CancelTask;
    function CancelTaskWithWait: TCloseAction;
    property isActive: Boolean read FisActive write FisActive;
  end;
Demo attached. Ach ja: Das ist ein proof-of-concept + ist offen für Verbesserung.

Jumpy 11. Jan 2021 08:06

AW: TTask/ITask + Synchronze + OnDestroy
 
Ich kenn mich mit Threads/Tasks nicht so aus, aber nur mal auf diesen Fall bezogen:

Könnte man den Thread nicht so bauen, dass er statt selber auf die GUI zuzugreifen eine Art Callback anbietet (den er ggf. synchronized abfackelt). Dann könnte man den Callback nämlich detachen, bevor man den Thread beendet. Denn warum soll der Thread noch die GUI updaten, wenn das Fenster eh gererade geschlossen werden soll.
Geht natürlich nur, wenn auf Threads von Außen nachträglich zugegriffen werden kann (wie gesagt, kenn mich damit nicht aus).


Alle Zeitangaben in WEZ +1. Es ist jetzt 17:49 Uhr.
Seite 3 von 3     123   

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