Wie kann ich das Fortschrittsbalken-Update schnell genug machen?

8

Ich verwende einen Fortschrittsbalken, um dem Benutzer anzuzeigen, wie weit der Prozess fortgeschritten ist. Es hat 17 Stufen und kann abhängig vom Wetter (gut, Datenbank) zwischen 5 Sekunden und zwei oder drei Minuten dauern.

Ich hatte kein Problem damit in XP, der Fortschrittsbalken ging gut, aber beim Testen in Vista fand ich, dass es nicht mehr der Fall ist.

Zum Beispiel: wenn es näher an 5 Sekunden dauert, könnte es ein 1/3 des Weges machen, bevor es verschwindet, weil es fertig ist. Obwohl es bei 17 von 17 ist, zeigt es es nicht. Ich glaube, das liegt an der Animation, die Vista auf Fortschrittsbalken setzt und die Animation kann nicht schnell genug enden.

Weiß jemand, wie ich das korrigieren kann?

Hier ist der Code:

Dies ist der Teil, der den Fortschrittsbalken aktualisiert. Warten ist das Formular mit dem Fortschrittsbalken.

%Vor%

Hier ist das wartende Formular:

%Vor%     
Malfist 10.06.2009, 18:09
quelle

9 Antworten

2

Versuchen Sie, den Aufruf der Methode waiting.setProgess() aufzurufen, da waiting in einem anderen Thread zu leben scheint. Dies wäre ein klassischer cross-Thread-Aufruf (worüber der Compiler Sie warnt, wenn Sie ihn lassen).

Da Control.Invoke etwas unhandlich ist, verwende ich normalerweise eine Erweiterungsmethode, die es mir erlaubt, einen Lambda-Ausdruck zu übergeben:

%Vor%

.

%Vor%     
VVS 10.06.2009, 19:34
quelle
31

Vista hat beim Aktualisieren des Fortschrittsbalkens einen Animationseffekt eingeführt - er versucht, sanft von der vorherigen Position zur neu eingestellten Position zu scrollen, was zu einer unangenehmen Zeitverzögerung beim Update des Controls führt. Die Verzögerung ist am auffälligsten, wenn Sie einen Fortschrittsbalken in großen Schritten springen, sagen wir von 25% auf 50% in einem Sprung.

Wie ein anderes Poster gezeigt hat, können Sie das Vista-Thema für die Fortschrittsleiste deaktivieren und es wird dann das Verhalten von XP-Fortschrittsbalken nachahmen.

Ich habe eine andere Problemumgehung gefunden: Wenn Sie den Fortschrittsbalken rückwärts setzen, wird er sofort zu diesem Ort malen. Wenn Sie also von 25% auf 50% springen möchten, würden Sie die (zugegeben hackische) Logik verwenden:

%Vor%

Ich weiß, ich weiß - es ist ein dummer Hack - aber es funktioniert!

    
Mark Lansdown 31.07.2009 18:35
quelle
9

Der Grund für dieses ganze Chaos ist der interpolierende Animationseffekt von Vista und W7. Es hat absolut nichts mit Thread-Blockierungsproblemen zu tun. Der Aufruf von setProgress () oder das direkte Setzen der Value-Eigenschaft löst einen Animationseffekt aus, der erklärt, wie man schummelt:

Ich habe einen Hack gemacht, um das Maximum nach einem festen Wert zu setzen. Die maximale Eigenschaft löst den Effekt nicht aus, sodass Sie den Fortschritt mit sofortiger Reaktion frei bewegen können.

Denken Sie daran, dass der tatsächlich angezeigte Fortschritt gegeben ist durch: ProgressBar.Value / ProgressBar.Maximum. Aus diesem Grund wird das folgende Beispiel den Fortschritt von 0 auf 100 verschieben, wie von i wiederholt:

%Vor%

Ich habe einige Skalierungsfaktoren hinzugefügt, die selbsterklärend sein sollten:

%Vor%     
Silas Hansen 24.11.2009 09:09
quelle
3

Es klingt , als würden Sie alles auf dem UI-Thread tun und somit die Nachrichtenpumpe nicht freigeben. Hast du versucht, das Smoothing wie BackgroundWorker und% ProgressChanged zu verwenden? Ein Beispiel finden Sie MSDN .

BackgroundWorker ist ideal zum Laden von externen Daten - aber beachten Sie, dass Sie keine Datenbindung durchführen sollten, bis Sie zum UI-Thread zurückkehren (oder verwenden Sie einfach Invoke / BeginInvoke , um die Arbeit an die UI-Thread).

    
Marc Gravell 10.06.2009 18:14
quelle
1

Ich verwende Mark Lansdowns ausgezeichnete Antwort als eine Erweiterungsmethode für das ProgressBar-Steuerelement.

%Vor%

Oder Sie können es auch so machen, dass die ProgressBar value -Eigenschaft nur zweimal statt dreimal gesetzt wird:

%Vor%

Rufen Sie es einfach mit der Erweiterungsmethode für ein ProgressBar-Steuerelement auf:

%Vor%

Wenn Sie wirklich möchten, können Sie auch die aktuelle Windows-Umgebung überprüfen und nur den Hack-Codeabschnitt für Windows Vista + ausführen, da die ProgressBar von Windows XP nicht über die langsame Fortschrittsanimation verfügt.

    
deegee 17.12.2013 17:54
quelle
1

Ausgehend von der Antwort von Silas Hansen scheint mir dieses jedes Mal perfekte Ergebnisse zu liefern.

%Vor%     
Nyerguds 07.08.2015 07:51
quelle
0

Erstens. Ich würde die Option CheckForIllegalCrossThreadCalls niemals deaktivieren.

Sekunde. Fügen Sie eine Aktualisierung () hinzu, nachdem Sie den Fortschritt aktualisiert haben. Nur weil du in einem anderen Thread arbeitest, bedeutet das nicht, dass dein GUI-Thread zur Aktualisierung übergeht.

    
Brad Bruce 10.06.2009 19:07
quelle
0

Ich habe das gleiche Problem. Ich habe ein Formular mit mehreren Fortschrittsbalken (der erste ist zum Beispiel Datei x / n, der untere ist Aufgabe y / m) Der obere Fortschrittsbalken aktualisiert TIMELY nicht, während der untere Fortschrittsbalken dies tut Programmatisch aktualisiere ich, invalidate, explizite Prozessmeldung, Refresh oder Sleep repariert es nicht. Lustige Sache ist, dass der untere Fortschrittsbalken und andere Komponente (Zeit verstrichener Text) in Ordnung ist. Dies ist ein reines Vista + Thema Problem (Animationen wie zuvor vorgeschlagen, XP oder Vista mit klassischen Thema funktioniert gut. Beim Anzeigen eines Meldungsfelds, nachdem der obere Fortschrittsbalken auf 100 (programmgesteuert, nicht visuell) gereist ist, sehe ich zuerst das Meldungsfeld und dann sehe ich, wie der Fortschritt abgeschlossen wird

Ich habe festgestellt, dass SetWindowTheme (ProgressBar.Handle, '', ''); wie erklärt auf Deaktivieren der Fortschrittsbalken-Animation auf Vista Aero funktioniert (aber ich habe jetzt alte Stil Fortschrittsbalken)

    
Frederic V 26.06.2009 14:09
quelle
0

Haben Sie Application.DoEvents (); ?

    
AdvanTiSS 12.11.2015 12:15
quelle