AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Zurück Delphi-PRAXiS Sprachen und Entwicklungsumgebungen Object-Pascal / Delphi-Language Delphi TTask.run und Form.close wie geht das richtig?
Thema durchsuchen
Ansicht
Themen-Optionen

TTask.run und Form.close wie geht das richtig?

Ein Thema von fisipjm · begonnen am 27. Okt 2021 · letzter Beitrag vom 7. Nov 2021
Antwort Antwort
Seite 1 von 2  1 2      
fisipjm

Registriert seit: 28. Okt 2013
251 Beiträge
 
#1

TTask.run und Form.close wie geht das richtig?

  Alt 27. Okt 2021, 14:04
Delphi-Version: 10.4 Sydney
Hi mal wieder in die Runde, in letzter Zeit spam ich das Forum ganz schön zu, aber die Hilfe ist einfach immer spitze

Folgendes "Problem".

Ich habe eine Form als "Muster Form" die Ruft optisch immer in gleicher Optik aufbereitete aber unterschiedliche Daten ab.
Auf der Form liegen komponenten zum REST Abruf und eine TAniIndicator komponente. ich hab im Grunde aktuell 2 Events, show und close. Die hab ich folgendermaßen aufgebaut und die Funktionieren auch im normalen Programmablauf.


Delphi-Quellcode:
procedure TMainForm.FormShow(Sender: TObject);
begin
 StringGridBindSourceDB1.Visible:=false;
  AniIndicator1.Position.X:= width/2 - AniIndicator1.Width;
  AniIndicator1.Position.Y:= Height/2 - AniIndicator1.Height;
  AniIndicator1.Enabled:=true;
  TTask.run(
  procedure
  begin
    LaaaaaangsameRESTAbfrageMachen;
    tthread.Synchronize(nil,procedure
    begin
      StringGridBindSourceDB1.Visible := true;
      AniIndicator1.Enabled:=false;
      AniIndicator1.Visible:=false;
    end);
  end);
end;

procedure TMainForm.FormClose(Sender: TObject; var Action: TCloseAction);
begin
  Action := TCloseAction.caFree;
end;
Ich bin komplett neu im Thema parallele Programmierung und hab das Gefühl da gibt's noch sehr viel für mich zu lernen. Mein Problem ist, wenn der Benutzer ungeduldig ist und die Form schon während des Ladevorgangs Schließt, dann crasht mir die Form komplett. Ich bekomme erst mal eine AccessViolation und danach ist die Form aber weiterhin im Objektinspektor verfübar anstatt sauber freigegeben. Ich geh mal davon aus ich muss das irgendwie im Thread abfangen, aber ich habe absolut keinen Ansatz wie.
Vielen Dank schon mal
  Mit Zitat antworten Zitat
Benutzerbild von himitsu
himitsu

Registriert seit: 11. Okt 2003
Ort: Elbflorenz
43.139 Beiträge
 
Delphi 12 Athens
 
#2

AW: TTask.run und Form.close wie geht das richtig?

  Alt 27. Okt 2021, 14:55
Delphi-Quellcode:
TThread.Synchronize(nil,procedure
begin
  if not (hier prüfen, ob die Form noch vorhanden ist) then
    Exit;
  StringGridBindSourceDB1.Visible := true;
Natürlich nicht auf Self oder irgendwas von der Form zugreifen.

Self kann man maximal verwenden, um z.B. in Screen.Forms zu suchen und dort ausschließlich den Zeiger vergleichen.
Gleichzeitig hoffen, dass es keine neue Form gibt, welche inzwischen an der alten Stelle ihren Speicherplatz fand.

Und nicht auf die Idee kommen vor dem Synchronize zu prüfen, weil während diesem Aufruf kann die Form immernoch verschwinden.




Aber, da du garantiert in LaaaaaangsameRESTAbfrageMachen auf Dinge in der Form zugreifst, bleibt nur noch OnCanClose der Form zu nutzen und wenn der Thread noch läuft, dann das Schließen abberechen.
Achtung: Free/Destroy im Code aufgerufen ignoriert OnClose und OnCloseQuery.

Und natürlich hast du da auch aufgepasst, dass im LaaaaaangsameRESTAbfrageMachen alles thread-save ist.
Garbage Collector ... Delphianer erzeugen keinen Müll, also brauchen sie auch keinen Müllsucher.
my Delphi wish list : BugReports/FeatureRequests
  Mit Zitat antworten Zitat
Benutzerbild von Uwe Raabe
Uwe Raabe

Registriert seit: 20. Jan 2006
Ort: Lübbecke
11.009 Beiträge
 
Delphi 12 Athens
 
#3

AW: TTask.run und Form.close wie geht das richtig?

  Alt 27. Okt 2021, 15:01
Na, da hast du jetzt aber Glück

Ich plane gerade einen Artikel über genau diese Problematik. Dort wird ein Interface als Vermittler verwendet.

Das Beispielprojekt für den Artikel hänge ich hier einfach mal ohne weitere Erklärung an. Statt des REST-Aufrufs wird hier zwar eine Dateisuche als long running task verwendet, aber das Prinzip ist dasselbe. Bei Unklarheiten einfach fragen.
Angehängte Dateien
Dateityp: zip AsyncGuard.zip (39,1 KB, 20x aufgerufen)
Uwe Raabe
Certified Delphi Master Developer
Embarcadero MVP
Blog: The Art of Delphi Programming
  Mit Zitat antworten Zitat
fisipjm

Registriert seit: 28. Okt 2013
251 Beiträge
 
#4

AW: TTask.run und Form.close wie geht das richtig?

  Alt 27. Okt 2021, 15:48
Delphi-Quellcode:
TThread.Synchronize(nil,procedure
begin
  if not (hier prüfen, ob die Form noch vorhanden ist) then
    Exit;
  StringGridBindSourceDB1.Visible := true;
Natürlich nicht auf Self oder irgendwas von der Form zugreifen.

Self kann man maximal verwenden, um z.B. in Screen.Forms zu suchen und dort ausschließlich den Zeiger vergleichen.
Gleichzeitig hoffen, dass es keine neue Form gibt, welche inzwischen an der alten Stelle ihren Speicherplatz fand.

Und nicht auf die Idee kommen vor dem Synchronize zu prüfen, weil während diesem Aufruf kann die Form immernoch verschwinden.




Aber, da du garantiert in LaaaaaangsameRESTAbfrageMachen auf Dinge in der Form zugreifst, bleibt nur noch OnCanClose der Form zu nutzen und wenn der Thread noch läuft, dann das Schließen abberechen.
Achtung: Free/Destroy im Code aufgerufen ignoriert OnClose und OnCloseQuery.

Und natürlich hast du da auch aufgepasst, dass im LaaaaaangsameRESTAbfrageMachen alles thread-save ist.
Okay, jetzt bin ich maximal verwirrt

Wenn ich nicht self verwenden kann (klingt logisch), was nutze ich dann?

LaaaaaangsameRESTAbfrageMachen holt sich über eine TBackendEndpoint komponente einen Stream und schiebt ihn eine FDMemtable. Was könnte da denn nicht Threadsafe sein?

Dein letzter Vorschlag hört sich nicht wirklich gut für mich an, das würde ja bedeuten der Bediener kann die Maske nicht schließen so lange der Thread noch läuft, sprich die Daten noch nicht geladen sind. Das würde ich gern vermeiden.
  Mit Zitat antworten Zitat
Benutzerbild von himitsu
himitsu

Registriert seit: 11. Okt 2003
Ort: Elbflorenz
43.139 Beiträge
 
Delphi 12 Athens
 
#5

AW: TTask.run und Form.close wie geht das richtig?

  Alt 27. Okt 2021, 16:02
Der Zeiger in Self kann genutzt werden, zum Suchen.
Vergleiche mit Screen.Forms prüft ja nur den Zeiger, aber nicht den Objektinhalt.

Wenn die Form schon weg ist, dann ist natürlich das Objekt, worauf "Self" zeigt, inkl. allem anderen dieser Form (abgesehn von lokalen Variablen und Funktionsparametern) auch weg.



Eine böse globale Variable oder ein Interface, um den "bin weg"-Status zu übergeben, das ginge ebenfalls.




Nja, an FDMemtable hängt doch bestimmt was dran?
z.B. ein Grid
Und schon macht es peng.

Hier könnte man aber
* entweder die Memtable vorübergehend von der DataSource abhängen
* oder die DataSource auf Enabled=False stellen
* oder schauen, ob das Grid eine Speerfunktion besitzt

Nur weil das Grid vielleicht unsichtbar ist, holt es sich dennoch intern schon die aktuellen Daten (reagiert auf Ereignisse der DataSource/DataSet)
Garbage Collector ... Delphianer erzeugen keinen Müll, also brauchen sie auch keinen Müllsucher.
my Delphi wish list : BugReports/FeatureRequests
  Mit Zitat antworten Zitat
fisipjm

Registriert seit: 28. Okt 2013
251 Beiträge
 
#6

AW: TTask.run und Form.close wie geht das richtig?

  Alt 28. Okt 2021, 07:09
Na, da hast du jetzt aber Glück

Ich plane gerade einen Artikel über genau diese Problematik. Dort wird ein Interface als Vermittler verwendet.

Das Beispielprojekt für den Artikel hänge ich hier einfach mal ohne weitere Erklärung an. Statt des REST-Aufrufs wird hier zwar eine Dateisuche als long running task verwendet, aber das Prinzip ist dasselbe. Bei Unklarheiten einfach fragen.
Moin Uwe,
schau mir dein Projekt gerade an, ich muss echt noch viel lernen.
Eine sache Off Topic, hast du eine gute Quelle oder Buchempfehlung um das Konzept und den Nutzen von Interfaces zu verstehen?

Ich glaube im groben habe ich es verstanden. Bei meinem Projekt ergibt sich aber jetzt ein Anschlussproblem. Aktuell ist mein Design so, das dass Laden beim show stattfindet die Main Form wird abgeleitet und lädt dann eben die "Grundfunktionen". Jetzt Gibt es aber den Fall, dass ich bei unterschieldichen Masken weitere Funktionalität (Felder, Werte , etc..) zur Verfügung stellen muss. Natürlich hat meine abgeleitete Form keinen Plan davon das in der PartenClass noch ein Thread läuft, dass führt dazu das ich in einen Deathlock laufe, wenn ich in der abgeleiteten Form an der GUI rumspielen will. Wäre das mit dem Interface auch gelöst? Ich befürchte nicht
  Mit Zitat antworten Zitat
fisipjm

Registriert seit: 28. Okt 2013
251 Beiträge
 
#7

AW: TTask.run und Form.close wie geht das richtig?

  Alt 28. Okt 2021, 07:12
Eine böse globale Variable oder ...
Moin,

hast du ein Beispiel für mich, nicht umbedingt um es zu benutzen, eher um es zu verstehen. Für mich sind Interfaces aktuell noch sehr abstrakt.
  Mit Zitat antworten Zitat
TigerLilly

Registriert seit: 24. Mai 2017
Ort: Wien, Österreich
1.174 Beiträge
 
Delphi 11 Alexandria
 
#8

AW: TTask.run und Form.close wie geht das richtig?

  Alt 28. Okt 2021, 07:15
Wenn du ein Fenster schließen möchtest, obwohl da noch ein Task läuft, musst du dieses tun:
1. das Schließen des Fensters abbrechen
2. den Task nach Möglichkeit rasch beenden

Du kannst in 1. dem User eine Info geben, dass da ein Task noch läuift + er es später nochmal probieren soll.
Du kannst in 1. einen Timer starten, der das Schließen nach xxx Sekunden automatisch nochmal probiert.
  Mit Zitat antworten Zitat
freimatz

Registriert seit: 20. Mai 2010
1.380 Beiträge
 
Delphi 11 Alexandria
 
#9

AW: TTask.run und Form.close wie geht das richtig?

  Alt 28. Okt 2021, 07:37
Könnte man nicht
1. das Schließen des Fensters abbrechen
2. den Task informieren, dass er sich weiter Arbeit sparen kann
3. Das Fenster unsichtbar machen (der Anwender kann dann weiter machen)
4. Wenn der Task fertig ist das Fenster schließen
  Mit Zitat antworten Zitat
Benutzerbild von Uwe Raabe
Uwe Raabe

Registriert seit: 20. Jan 2006
Ort: Lübbecke
11.009 Beiträge
 
Delphi 12 Athens
 
#10

AW: TTask.run und Form.close wie geht das richtig?

  Alt 28. Okt 2021, 08:58
schau mir dein Projekt gerade an, ich muss echt noch viel lernen.
Das kann aber wohl jeder hier sagen - mich eingeschlossen. Der Artikel dazu wird dann hoffentlich Erleuchtung bringen.

Eine sache Off Topic, hast du eine gute Quelle oder Buchempfehlung um das Konzept und den Nutzen von Interfaces zu verstehen?
Da fällt mir spontan Coding in Delphi von Nick Hodges ein.

Wäre das mit dem Interface auch gelöst? Ich befürchte nicht
Die Beschreibung ist dazu noch nicht konkret genug. Lösen lässt sich in der Regel aber fast alles. Ob nun mit Interfaces oder was anderem muss man sehen.
Uwe Raabe
Certified Delphi Master Developer
Embarcadero MVP
Blog: The Art of Delphi Programming
  Mit Zitat antworten Zitat
Antwort Antwort
Seite 1 von 2  1 2      


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 22:50 Uhr.
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