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/)
-   -   Delphi Problem mit Thread und ProgressBar (https://www.delphipraxis.net/142081-problem-mit-thread-und-progressbar.html)

Helmi 21. Okt 2009 17:58


Problem mit Thread und ProgressBar
 
Hallo,

ich habe ein Programm mit einem Thread.

In diesem Thread werden im Execute 5 Proceduren aufgerufen, abhängig ob jeweils eine Variable aktiv ist oder nicht.
Nach jeder Procedure wird eine Procedure mit Synchronize aufgerufen, die dann im Hauptthread eine ProgressBar-Position
ändert.

Beim Debuggen fällt mir auf, dass nach jeder Procedure der Code für die ProgressBar-Positions-Änderung aufgerufen wird.
Die ProgressBar ändert aber erst die Position wenn der Thread nicht mehr läuft.

Hätte jemand eine Idee, was das Problem sein könnte?

Luckie 21. Okt 2009 18:03

Re: Problem mit Thread und ProgressBar
 
Zitat:

Zitat von Helmi
Hätte jemand eine Idee, was das Problem sein könnte?

Dass du uns keinen Code zeigst?

Helmi 21. Okt 2009 18:10

Re: Problem mit Thread und ProgressBar
 
Liste der Anhänge anzeigen (Anzahl: 1)
hier mal das projekt

himitsu 21. Okt 2009 18:19

Re: Problem mit Thread und ProgressBar
 
Windows Vista/Seven?

Da ändert sich die ProgressBar nicht sofort, sondern paßt sich stetig an (liegt an Windows)

Luckie 21. Okt 2009 18:25

Re: Problem mit Thread und ProgressBar
 
Zitat:

Zitat von Helmi
hier mal das projekt

Ist es denn so schwer einfach den relevanten Code hier zu posten?

Helmi 21. Okt 2009 18:26

Re: Problem mit Thread und ProgressBar
 
Zitat:

Zitat von Luckie
Zitat:

Zitat von Helmi
hier mal das projekt

Ist es denn so schwer einfach den relevanten Code hier zu posten?

Mit nix zu frieden der Herr!!

Helmi 21. Okt 2009 18:29

Re: Problem mit Thread und ProgressBar
 
Zitat:

Zitat von himitsu
Windows Vista/Seven?

Da ändert sich die ProgressBar nicht sofort, sondern paßt sich stetig an (liegt an Windows)

Ja ist Vista

Interessanterweise hab ich auch andere Projekte mit ner Progressbar die sich ständig ändert, aber in
diesen Projekte funktionierts problemlos.

Ich seh nur keinen Unterschied wieso es bei dem einem funktioniert, beim Anderen aber nicht

himitsu 21. Okt 2009 18:34

Re: Problem mit Thread und ProgressBar
 
zurücksetzen passiert quasi sofort

Lösung:
Delphi-Quellcode:
PB.Position := i + 1;
PB.Position := i;
bzw.
Delphi-Quellcode:
PB.Position := Max(i + 1, PB.Max - 1);
PB.Position := i;

Helmi 21. Okt 2009 18:45

Re: Problem mit Thread und ProgressBar
 
Zitat:

Zitat von himitsu
zurücksetzen passiert quasi sofort

Lösung:
Delphi-Quellcode:
PB.Position := i + 1;
PB.Position := i;
bzw.
Delphi-Quellcode:
PB.Position := Max(i + 1, PB.Max - 1);
PB.Position := i;

Was meist du mit zurücksetzen?
Hab deine Codes mal getestet, leider ändert sich nichts am Verhalten

Tryer 21. Okt 2009 19:12

Re: Problem mit Thread und ProgressBar
 
Da ich nichts von {APPTYPE CONSOLE} und WriteLn - Ausgaben sehe: Hast Du den abwechselnden Aufruf beim Debuggen vielleicht mit Haltepunkten hervorgerufen? Vielleicht kommt das Formular dank zahlreicher Sync-Anfragen garnicht zum neuzeichnen. Ob die Position sich überhaupt ändert könnte vermutlich ein nachgeschaltetes ProcessMessages zeigen.

Grüsse, Dirk

Helmi 21. Okt 2009 19:17

Re: Problem mit Thread und ProgressBar
 
Zitat:

Zitat von Tryer
Da ich nichts von {APPTYPE CONSOLE} und WriteLn - Ausgaben sehe: Hast Du den abwechselnden Aufruf beim Debuggen vielleicht mit Haltepunkten hervorgerufen? Vielleicht kommt das Formular dank zahlreicher Sync-Anfragen garnicht zum neuzeichnen. Ob die Position sich überhaupt ändert könnte vermutlich ein nachgeschaltetes ProcessMessages zeigen.

Ich habe schon ProcessMessages eingebaut, als auch mal ein Sleep, weil ich mir das gleiche wie du auch schon dachte
aber es nützt nichts.

Ich sehe aber, dass diese Procedur angesprungen wird, bzw. durchlaufen wird
aber die Progressbar geht nicht.

Ich hab auch mal versucht, ein Label beschreiben zu lassen, aber auch das passiert erst, wenn der Thread zu ende ist

[Edit]

Ich hab jetzt mal einen Test gemacht und hab festgestellt, dass sich da irgendwas "ansammelt". Denn, wenn ich im Thread
nach der try/finally-Block ein Sleep(10000) einsetzt, dann seh ich dass die Progressbar auf einmal aufgebaut wird und
danach erst beendet sich der Thread (nach Ablauf der Sleep-Zeit).

Delphi-Quellcode:
procedure TThreadUnit.Execute;
var
  b_Allgemein: Boolean;
  b_Kanal   : Boolean;
  b_Achse   : Boolean;
  b_Antrieb : Boolean;
  b_Anzeige : Boolean;

  StringList_NCUpgrade: TStringList;

begin
  inherited;

  //Variablen leeren
  i_Anzahl_Allgemein := 0;
  i_Anzahl_Kanal     := 0;
  i_Anzahl_Achse     := 0;
  i_Anzahl_Antrieb   := 0;
  i_Anzahl_Anzeige   := 0;

  //NC-Upgradefile als String holen
  Synchronize(NCUpgrade_holen);

  //Maschinendaten-Auswahl holen
  Synchronize(MDAuswahl_holen);

  //Variablen beschreiben
  b_Allgemein := (i_MDAuswahl and 1) = 1;
  b_Kanal    := (i_MDAuswahl and 2) = 2;
  b_Achse    := (i_MDAuswahl and 4) = 4;
  b_Antrieb  := (i_MDAuswahl and 8) = 8;
  b_Anzeige  := (i_MDAuswahl and 16) = 16;

  //StringList erzeugen
  StringList_NCUpgrade := TStringList.Create;

  try
    StringList_NCUpgrade.Text := S_NCUpgrade;

    //wenn die CheckBox "Allgemein" aktiv ist, dann die MD´s "Allgemein" auslesen
    If b_Allgemein then
      begin
        i_Anzahl_Allgemein := Allgemein_Maschinendaten_auslesen(StringList_NCUpgrade);

        Synchronize(MDAuslesen_fertig);
      end;

    //wenn die CheckBox "Kanal" aktiv ist, dann die MD´s "Kanal" auslesen
    If b_Kanal then
      begin
        i_Anzahl_Kanal     := Kanal_Maschinendaten_auslesen(StringList_NCUpgrade);

        Synchronize(MDAuslesen_fertig);
      end;

    //wenn die CheckBox "Achs" aktiv ist, dann die MD´s "Achs" auslesen
    If b_Achse then
      begin
        i_Anzahl_Achse     := Achs_Maschinendaten_auslesen(StringList_NCUpgrade);

        Synchronize(MDAuslesen_fertig);
      end;

    //wenn die CheckBox "Antrieb" aktiv ist, dann die MD´s "Antrieb" auslesen
    If b_Antrieb then
      begin
        i_Anzahl_Antrieb   := Antrieb_Maschinendaten_auslesen(S_NCUpgrade);

        Synchronize(MDAuslesen_fertig);
      end;

    //wenn die CheckBox "Anzeige" aktiv ist, dann die MD´s "Anzeige" auslesen
    If b_Anzeige then
      begin
        i_Anzahl_Anzeige   := Anzeige_Maschinendaten_auslesen(StringList_NCUpgrade);

        Synchronize(MDAuslesen_fertig);
      end;
  finally
    //StringList löschen und freigeben
    FreeAndNil(StringList_NCUpgrade);
  end;

  sleep(10000);

  //mit MainForm-Procedure synchronisieren
  Synchronize(fertig);
end;

messie 21. Okt 2009 19:54

Re: Problem mit Thread und ProgressBar
 
Hallo Helmi,

ich habe heute schon zu lange vor dem Rechner gesessen, um noch alles durchzulesen.

Mir fällt aber inherited auf. Ich weiß nicht, was der Thread dann alles Ererbtes macht.

Das habe ich so noch nie benutzt und auch noch nie davon gehört. Vielleicht lässt Du das mal weg.

Abgesehen davon musst Du natürlich immer darauf achten, dass niemand Anderes auf denselben Speicher zugreift (es ist keine Synchronisation mit anderen Threads sichtbar)

Grüße, Messie

Sir Rufo 21. Okt 2009 20:00

Re: Problem mit Thread und ProgressBar
 
Zitat:

Zitat von messie
Hallo Helmi,

ich habe heute schon zu lange vor dem Rechner gesessen, um noch alles durchzulesen.

Mir fällt aber inherited auf. Ich weiß nicht, was der Thread dann alles Ererbtes macht.

Das habe ich so noch nie benutzt und auch noch nie davon gehört. Vielleicht lässt Du das mal weg.

Abgesehen davon musst Du natürlich immer darauf achten, dass niemand Anderes auf denselben Speicher zugreift (es ist keine Synchronisation mit anderen Threads sichtbar)

Grüße, Messie

Das mit dem inherited wird am Anfang einmal aufgerufen und dann ist gut, spielt also keine Geige :mrgreen:

Helmi 21. Okt 2009 20:00

Re: Problem mit Thread und ProgressBar
 
Zitat:

Zitat von messie
ich habe heute schon zu lange vor dem Rechner gesessen, um noch alles durchzulesen.

Mir fällt aber inherited auf. Ich weiß nicht, was der Thread dann alles Ererbtes macht.

Das habe ich so noch nie benutzt und auch noch nie davon gehört. Vielleicht lässt Du das mal weg.

Abgesehen davon musst Du natürlich immer darauf achten, dass niemand Anderes auf denselben Speicher zugreift (es ist keine Synchronisation mit anderen Threads sichtbar)

Ich habe es jetzt mal ohne inherited gemacht, aber das bringt auch nichts.
Es gibt nur einen Thread (jedenfalls von mir erzeugtem Thread) und da ist meines Wissens nach keine Synchronisation mit einem anderen Thread vorhanden

Tryer 21. Okt 2009 20:18

Re: Problem mit Thread und ProgressBar
 
Versuch mal
Delphi-Quellcode:
PostMessage(MainForm.Progressbar.Handle, PBM_SETPOS,
  MainForm.Progressbar.Position + 1, 0);
an Stelle des Synchronize - Aufrufs (event. auch noch mit zusätzlichem Sleep(0);). Vielleicht wacht der MainThread darüber aus dem Idle / CheckSynchronize auf. Unter D7 / XP kann ich das Problem leider nicht nachvollziehen.

messie 21. Okt 2009 20:23

Re: Problem mit Thread und ProgressBar
 
Konsequenter wäre es, wenn die mit Synchronize aufgerufenen Routinen Teil des Threads wären. Bei Dir sind sie global deklariert und gehören damit eigentlich dem MainThread. Wenn Du dort das Anpassen des Progressbar aufrufst, würde ich ein Application.ProcessMessages nach Aufruf der Routine des MainForm platzieren.

Grüße, Messie

Tryer 21. Okt 2009 20:26

Re: Problem mit Thread und ProgressBar
 
Zitat:

Zitat von messie
Bei Dir sind sie global deklariert und gehören damit eigentlich dem MainThread.

Logisch gesehen sind sie das wenn sie mit Synchronize aufgerufen werden (Direkter Aufruf aus MainThread ok, direkter Aufruf aus Thread: kritisch).
Das ProcessMessages nix bringt hat er doch schon erwähnt.

himitsu 21. Okt 2009 20:32

Re: Problem mit Thread und ProgressBar
 
Die Progressbar läuft jetzt nur einmal durch, bzw. die soll?

Und die PB mal rückwärts laufen zu lassen ändert auch nix an der Darstelung?
Delphi-Quellcode:
PB.Position := PB.Max - i - 1;
Wie gesagt, seit Vista hat MS die Darstellung geändert und jetzt läuft sie halt nicht mehr ruckartig

z.B. vom Pos=10 gleich auf Pos=30, sondern sie bewegt sich "langsam" (Pixelweise) auf den neuen/aktuellen Wert zu.
Aber beim einem Rückschritt (Pos wurde kleiner) soll sie sich angeblich sofort/sprungartig auf den neuen Wert bewegen.

Helmi 21. Okt 2009 20:37

Re: Problem mit Thread und ProgressBar
 
Zitat:

Zitat von messie
Konsequenter wäre es, wenn die mit Synchronize aufgerufenen Routinen Teil des Threads wären. Bei Dir sind sie global deklariert und gehören damit eigentlich dem MainThread. Wenn Du dort das Anpassen des Progressbar aufrufst, würde ich ein Application.ProcessMessages nach Aufruf der Routine des MainForm platzieren.

Daraus werd ich nicht schlau!
Die mit Synchronize aufgerufenen Routinen sind im private-Bereich des Threads deklariert - und so Teil des Threads.
Nur darin werden dann Proceduren der MainForm aufgerufen

BAMatze 21. Okt 2009 20:59

Re: Problem mit Thread und ProgressBar
 
Hallo,

ich hatte auch ein ähnliches Problem vor kurzem, da hat der Thread erst deutlich nach einer Aktion die Anzeige der geänderten Form aktualisiert. Schau dir das mal an Ich konnte das Problem durch ein Aufrufen der MainForm.Refresh am Ende der Prozeduren, welche in Syncronize aufgerufen werden, lösen. Konnte das leider in deinem Projekt nicht testen, da etliche deiner Uses-Klauseln in meinem TE2006 hier zu Hause nicht akzeptiert werden. Habe einfach mal mit der Suchfunktion deine MainUnit und deine ThreadUnit durchsucht und nichts gefunden in der Art.

Hoffe das hilft dir vieleicht etwas
BAMatze

Helmi 21. Okt 2009 21:11

Re: Problem mit Thread und ProgressBar
 
Zitat:

Zitat von BAMatze
Hallo,

ich hatte auch ein ähnliches Problem vor kurzem, da hat der Thread erst deutlich nach einer Aktion die Anzeige der geänderten Form aktualisiert. Schau dir das mal an Ich konnte das Problem durch ein Aufrufen der MainForm.Refresh am Ende der Prozeduren, welche in Syncronize aufgerufen werden, lösen. Konnte das leider in deinem Projekt nicht testen, da etliche deiner Uses-Klauseln in meinem TE2006 hier zu Hause nicht akzeptiert werden. Habe einfach mal mit der Suchfunktion deine MainUnit und deine ThreadUnit durchsucht und nichts gefunden in der Art.

Hoffe das hilft dir vieleicht etwas
BAMatze

Hat leider nicht funktioniert.
Das Verhalten ist noch immer das gleiche.

Wenn du die Komponenten:
VistaMan: TVistaMan;
VistaAltFix: TVistaAltFix;
OneInstance: TOneInstance;

und die Uses-Klauseln: VistaMan, VistaAltFix, OneInstance

rauslöscht, dann müsste es gehen zu kompilieren.

Sir Rufo 21. Okt 2009 21:38

Re: Problem mit Thread und ProgressBar
 
Liste der Anhänge anzeigen (Anzahl: 2)
Ich habe im Anhang mal ein Beispül-Projekt angehängt (Source und Exe).

Der Thread tut watt und die ProgressBar auf dem Form wird brav aktualisiert.

Die Programm-Teile sind getrennt in Arbeitsteil (Thread) und Anzeigeteil (Form).

Dieses funktioniert so unter Vista x32 und Windows 7 x64.

cu

Oliver

axo: Thread starten mit Klick auf den Button (wer hätte das vermutet) :mrgreen:


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