Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   GUI-Design mit VCL / FireMonkey / Common Controls (https://www.delphipraxis.net/18-gui-design-mit-vcl-firemonkey-common-controls/)
-   -   Zugriff auf TProgressbar.Position aus TThread.Queue (https://www.delphipraxis.net/211464-zugriff-auf-tprogressbar-position-aus-tthread-queue.html)

TurboMagic 19. Sep 2022 21:09

Zugriff auf TProgressbar.Position aus TThread.Queue
 
Benutze D11.2 und Versuche mittels TThread.Queue ein Progressbar aus einem Task heraus zu aktualisieren. Das crasht jedoch. Ein Label das in der selben Methode den selben Wert ausgibt crasht nicht.

Woran kann es liegen?

Uwe Raabe 19. Sep 2022 21:18

AW: Zugriff auf TProgressbar.Position aus TThread.Queue
 
Zitat:

Zitat von TurboMagic (Beitrag 1512089)
Benutze D11.2 und Versuche mittels TThread.Queue ein Progressbar aus einem Task heraus zu aktualisieren. Das crasht jedoch. Ein Label das in der selben Methode den selben Wert ausgibt crasht nicht.

Woran kann es liegen?

Wie genau machst du es?

himitsu 20. Sep 2022 01:55

AW: Zugriff auf TProgressbar.Position aus TThread.Queue
 
https://www.delphipraxis.net/196442-...ml#post1512030 :stupid:

Dennis07 20. Sep 2022 06:16

AW: Zugriff auf TProgressbar.Position aus TThread.Queue
 
Und wenn du es mit TTask.Run machst? (Vergiss nicht das Synchronize, ansonsten ruft der das aus einem anderen Thread auf!)

himitsu 20. Sep 2022 08:32

AW: Zugriff auf TProgressbar.Position aus TThread.Queue
 
Delphi-Referenz durchsuchenTThread.Queue = Synchronize .... nur nicht jetzt, sondern später :zwinker:

Darum ist auch das Wie wichtig.
z.B. Variable benutzen, die es "dann" nicht mehr gibt = ungünstig
oder Variable benutzen, die "dann" im Thread überschrieben sein/werden kann = ungünstig, weil nicht mehr synchron
oder ...

TurboMagic 20. Sep 2022 11:29

AW: Zugriff auf TProgressbar.Position aus TThread.Queue
 
Sitze gerade vor einem anderen PC aber im Prinzip so:

Delphi-Quellcode:
type
  TOnProgress = procedure(Sender: TObject; Progress: UInt32) of Object;

  TMyWorker = class(TObject)
  private
   FOnProgress : TOnProgress;
   procedure ReportProgress(Progress: UInt32);
  public
    procedure DoIt;
    property OnProgress : TOnProgress read FOnProgress write FOnProgress;
  end;

procedure TMyWorker.Dot;
begin
  TTask.Run(
    for var i := 0 to 100 do
    begin
      ReportProgress(i);
      sleep(50);
    end);
end;

procedure TMyWorker.ReportProgress(Progress: UInt32);
begin
  TThread.Queue(procedure
                 if Assigned(FOnProgress) then
                   FOnProgress(self, Progress);
                end);
end;

[..]

TMainForm = class(TForm)
  pb_Progrsss : TProgressBar;
  Label1: TLabel;
private
  FWorker : TMyWorker ;
public
  procedure OnProgress(Sender: TObject; Progress: UInt32);
  procedure DoSomething;
end;

[..]

procedure TMainForm.OnProgress(Sender: TObject; Progress: UInt32);
begin
  Label1.Caption := Progress.ToString;
  pb_Progress.Position := Progress;
end;

procedure TMainForm.DoSomething;
begin
  FWorker.DoIt;
end;
So ungefähr. Ja, was wirklich im Task läuft ist noch etwas demo mäßig und wird später ersetzt.

himitsu 20. Sep 2022 11:52

AW: Zugriff auf TProgressbar.Position aus TThread.Queue
 
Der Progress-Parameter ist sicher, weil da macht der Generic die anonyme Methode sich eine Copie von.

Bei OnProgress hat nicht, denn dort hat der nur eine Kopie des Self, welches nur so lange gültig ist, wie die TMyWorker-Instanz läuft.
Bei Synchronize kein Problem ... aber bem Queue muß man aufpassen.
Allerdings könnte man sich auch eine lokale Variable für OnProgress in ReportProgress anlegen ... dann ist TMyWorker egal und man muß nur noch auf das achten, wohin das Event geht, also TMainForm (hier gäbe es in Queue(procedure Möglichkeiten das gegenzuprüfen, z.B. über Application.MainForm, bzw. über Screen.Forms, ob der Form-Zeiger noch valide ist).


Ansonsten:
TStaticText, bzw. TPanel anstatt TLabel
und dann kann es als "richtiges" WinControl auch auf Messages reagieren,
also SendMessage(WM_SETTEXT), bzw SetWindowText und die ProgessBar auf PostMessage mit PBM_SETPOS.

SendMessage, weil wegen dem "PChar", der ja bei Ausführung noch gültig sein muß.
In das WndProc des Label kann man auch eine Message mit "Interger"-Parameter gängen, welcher Diesen nach String übersetzt und an Caption übergibt ... das ginge dann wieder als PostMessage.

PostMessage direkt an das Fenster/Control ... verschwindet das Fenster/Control vor Abarbeitung der Message in der MessageQueue (PostMessage), dann räumt Windows diese Message orgendlich auf ... kein eventuelle Ausführen nach Freigabe des Controls.

Bei der TThread.Queue wäre es also nett, könnte man sie auch (optional) an ein TWinControl/HWND oder zumindestens an ein TControl hängen. (dann würde Windows/Delphi die Prüfung ob noch da übernehmen)

TurboMagic 20. Sep 2022 12:00

AW: Zugriff auf TProgressbar.Position aus TThread.Queue
 
Bitte nicht an dem Sender Parameter aufhängen.
Der wird ja im GUI gar nicht benutzt.

Die Anzeige des Wertes per Label funktioniert, bei der Zuweisung des Position des Progress Bar knallt es.
C0000005 oder so...

Meiner Meinung nach dürfte es doch da aber gar kein Problem geben, da die Queue es ja dann abarbeitet,
wenn es für den GUI passt.

=> wo ist mein Problem hier? Ja, mit Messages könnte man das sicher lösen, dann wäre aber die
Geschäftslogik an Windows gebunden...

Grüße
TurboMagic

Uwe Raabe 20. Sep 2022 12:47

AW: Zugriff auf TProgressbar.Position aus TThread.Queue
 
Wenn du dann wieder vor dem passenden PC sitzt, mach doch bitte ein minimales Beispiel, damit wir das hier auch nachvollziehen können.

DieDolly 20. Sep 2022 19:18

AW: Zugriff auf TProgressbar.Position aus TThread.Queue
 
Zitat:

Zitat von himitsu (Beitrag 1512096)

Naja bei mir war es anders. Ich versuche nicht direkt aus einem Thread heraus die ProgressBar zu setzen. Ich gehe da über PostMessage.

TurboMagic 20. Sep 2022 20:50

AW: Zugriff auf TProgressbar.Position aus TThread.Queue
 
Liste der Anhänge anzeigen (Anzahl: 1)
Komisch, ich habe jetzt das gewünschte Testprogramm geschrieben, siehe Anhang.
Nur: es knallt da nicht beim Zugriff auf den Progressbar, das Label wird aber
nie aktualisiert :?

Bin verwirrt.

Grüße

TurboMagic

jaenicke 20. Sep 2022 20:53

AW: Zugriff auf TProgressbar.Position aus TThread.Queue
 
Zitat:

Zitat von TurboMagic (Beitrag 1512155)
Nur: es knallt da nicht beim Zugriff auf den Progressbar, das Label wird aber
nie aktualisiert :?

Da du im Kontext des Hauptthreads (in Queue) ein Sleep drin hast, blockierst du den Hauptthread.

Ja, bei mir gibt es auch keinen Fehler. Da muss etwas anderes los sein. Kannst du vielleicht einen Screenshot von Delphi machen, wenn der Fehler im echten Projekt auftritt? Damit man den Stacktrace usw. sieht?

TurboMagic 20. Sep 2022 21:18

AW: Zugriff auf TProgressbar.Position aus TThread.Queue
 
Liste der Anhänge anzeigen (Anzahl: 1)
Das mit dem Sleep: Duh! War aber nur im Testprogramm so.
Anbei ein Screenshot und siehe da: kein Stsck Trace!
Crash ist in Zeile 190.

Uwe Raabe 20. Sep 2022 21:58

AW: Zugriff auf TProgressbar.Position aus TThread.Queue
 
In deinem ersten Beispiel hattest du das Sleep direkt hinter dem ReportProgress. Damit bekommt man nicht nur einen flüssigen Ablauf hin, sondern das Label wird auch aktualisiert. Fehlt das Sleep, schreibt der Thread die Synchronize-Queue voll und der Hauptthread hat keine Zeit das Label zu aktualisieren. Am Ende steht es dann auf 200.

Wenn es an diesem Beispiel nicht auftritt, dann ist das Beispiel noch nicht genau genug an das Realprogramm angepasst.

jaenicke 20. Sep 2022 22:05

AW: Zugriff auf TProgressbar.Position aus TThread.Queue
 
Zitat:

Zitat von TurboMagic (Beitrag 1512157)
Das mit dem Sleep: Duh! War aber nur im Testprogramm so.
Anbei ein Screenshot und siehe da: kein Stsck Trace!

Dafür musst du noch auf Anhalten drücken. ;-)

himitsu 20. Sep 2022 22:42

AW: Zugriff auf TProgressbar.Position aus TThread.Queue
 
Und eventuell noch einmal F7 ... direkt nach einer Exception bekommt Delphi das manchmal/oftmals nicht sofort hin, während der Stack noch zwischen zwei Codezeilen hängt.

TurboMagic 21. Sep 2022 19:43

AW: Zugriff auf TProgressbar.Position aus TThread.Queue
 
Liste der Anhänge anzeigen (Anzahl: 1)
Ok, hier ein neuer Screenshot, diesmal mit Callstack.

himitsu 21. Sep 2022 20:14

AW: Zugriff auf TProgressbar.Position aus TThread.Queue
 
mach da mal ein Try-Except drumrum und kopieren den Code "nochmal" ins Except ... dann kannst du nach dem Knall nochmal manuell reindebuggen (F7) und überall vorher sehen, was die Variablen sagen.

TurboMagic 21. Sep 2022 20:21

AW: Zugriff auf TProgressbar.Position aus TThread.Queue
 
Liste der Anhänge anzeigen (Anzahl: 1)
Scheint da alles nil zu sein.
Welche Variable wäre da interessant?
Siehe Anhang.

himitsu 21. Sep 2022 20:24

AW: Zugriff auf TProgressbar.Position aus TThread.Queue
 
Du bist nicht zufällig grade dabei die Form/Anwendung zu schließen, bzw. es wurde kurz vorher gemacht?

TurboMagic 21. Sep 2022 20:26

AW: Zugriff auf TProgressbar.Position aus TThread.Queue
 
Eigentlich nicht. Aber ich probiere mal was. Moment... Stay tuned... ;-)

TurboMagic 21. Sep 2022 20:34

AW: Zugriff auf TProgressbar.Position aus TThread.Queue
 
Hah! Du hattest recht! Der Button zum Starten der Aktion hatte ModalResult = mrOK und
hat somit irgendwie das Fenster geschlossen.

Danke!

Grüße
TurboMagic


Alle Zeitangaben in WEZ +1. Es ist jetzt 13:18 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