Laden...

ProgressBar ist bei 100% nicht ganz gefüllt

Erstellt von tööö vor 14 Jahren Letzter Beitrag vor 14 Jahren 7.813 Views
T
tööö Themenstarter:in
92 Beiträge seit 2006
vor 14 Jahren
ProgressBar ist bei 100% nicht ganz gefüllt

Hi,

ich hab da ein Problem mit meiner ProgressBar. Ich arbeite mit einem Backgroundworker und die ProgressBar wird in der Methode "ProgressChanged" gefüllt. Bei 100% ist sie aber nicht ganz gefüllt, sondern nur zu (sagen wir mal) 90%. Aber 100% wird auf jeden Fall an die "ProgressChanged"-Methode übergeben, da ich ja den Prozentwert in einem Laben ausgebe.

Hier mal die "DoWork"-Methode, welche dann die "ProgressChanged" aufruft:


for (int i = 0; i < this.iAnzahlDateien; i++)
            {
                // Die übrigegebliebenen Dateien holen
                this.dateinamen = Directory.GetFiles(this.tempOrdner, "*", SearchOption.AllDirectories);
                zufall = rand.Next(this.iAnzahlDateien - i - 1);
                tempName = this.dateinamen[zufall].Substring(this.dateinamen[zufall].LastIndexOf("\\") + 1);
                zielPfad = e.Argument.ToString() + "\\" + tempName;
                File.Move(this.dateinamen[zufall], zielPfad);

                // Statusbalken anpassen
                this.bckWork_Mischen.ReportProgress(Convert.ToInt32(i * 100 / this.iAnzahlDateien), tempName);
            }

Hier wird aus einem Ordner per Zufall immer eine Datei genommen und in einem anderen Ordner verschoben.

Die "ProgressChanged"-Methode sieht folgendermaßen aus:

private void bckWork_Mischen_ProgressChanged(object sender, ProgressChangedEventArgs e)
        {
            if (e.UserState.ToString() == "Ausschneiden")
            {
                this.lbl_statusnachricht.Text = "Vorbereitung";
                this.prg_prozent.Value = e.ProgressPercentage;
                this.lbl_progressProzent.Text = e.ProgressPercentage.ToString() + "%";
            }
            else
            {
                this.lbl_statusnachricht.Text = "Datei:\n" + e.UserState.ToString();
                this.prg_prozent.Value = e.ProgressPercentage;
                this.lbl_progressProzent.Text = e.ProgressPercentage.ToString() + "%";
            }
        }

Vielleicht ist das ja ein Phänomen, welches öfter auftritt und ihr gleich eine Lösung parat habt? Ich habe schon viel rumprobiert, aber wenn ich die ProgressBar per Code auf 100 stelle, ist sie nicht ganz gefüllt. Fülle ich sie stattdessen im Designer mit dem Wert 100 (Eigenschaft "Value"), so wirds beim Ausführen des Programms richtig angezeigt.

Ich hoffe auf eure Hilfe, weil selbst weiß ich leider nicht mehr weiter...

Liebe Grüße
tööö

916 Beiträge seit 2008
vor 14 Jahren

Hallo tööö,

du redest hier immer von Prozent, wie ist denn dein Minimum und dein Maximum deiner Progressbar? Hast du mal geschaut das auch das Maximum und das Value gleich sind (bei 100%)?

Again what learned...

T
tööö Themenstarter:in
92 Beiträge seit 2006
vor 14 Jahren

Hi,

Minimum ist 0 und Maximum ist 100. Sind ja eh die Standardwerte 😉

Liebe Grüße
tööö

916 Beiträge seit 2008
vor 14 Jahren

Schon komisch, kannst du mal Testhalber ein Invalidate an der Progressbar aufrufen sobald du den Value change durchführst. Sollte zwar implizit von der PB gemacht werden aber probiere es trotzdem mal.

Again what learned...

T
tööö Themenstarter:in
92 Beiträge seit 2006
vor 14 Jahren

Hat leider auch nichts geholfen.
Hatte mit der ProgressBar sonst auch nie Probleme, verstehs ja jetzt selber nicht 😦

So sieht es dann bei 100% aus.
Im "RunWorkerCompleted" hab ich nun auch folgendes gemacht:

this.lbl_statusnachricht.Text = "Mischen erfolgreich!";
            this.lbl_progressProzent.Text = "100%";
            this.prg_prozent.Value = 100;
            this.prg_prozent.Invalidate();

Aber trotzdem sieht es dann so aus wie im Anhang zu sehen...

1.665 Beiträge seit 2006
vor 14 Jahren

Das einzige, was ich mir vorstellen könnte, ist, dass du den Max-Wert zwischendurch änderst.
Ansonsten bau das nochmal in einem Testprojekt zusammen. Spätestens da sollte das Missgeschick klar werden.

Schließt du den Dialog mit der ProgressBar direkt wieder, wenn diese 100 erreicht hat? (sofern es eine separate Form dafür gibt)

916 Beiträge seit 2008
vor 14 Jahren

Oder setzt dort mal


m_progressbar.Value = m_progressbar.Maximum;

Again what learned...

T
tööö Themenstarter:in
92 Beiträge seit 2006
vor 14 Jahren

@rollerfreak:
Das hat leider auch nichts gebracht. Hätte mich auch stark gewundert, leider...

@JunkyXL:
Das war schonmal ein guter Hinweis. Im RunWorkerCompleted mach ich auch folgendes, um die Anwendung nach dem Durchlaufen gleich zu schließen:

this.lbl_statusnachricht.Text = "Mischen erfolgreich!";
            this.lbl_progressProzent.Text = "100%";
            this.prg_prozent.Value = 100;
            this.prg_prozent.Invalidate();
            this.lbl_statusnachricht.Refresh();
            this.lbl_progressProzent.Refresh();
            this.prg_prozent.Refresh();
            Thread.Sleep(1500);
            Application.Exit();

Kommentier ich ein paar Zeilen aus und lasse nur das hier stehen:

this.lbl_statusnachricht.Text = "Mischen erfolgreich!";
            this.lbl_progressProzent.Text = "100%";
            this.prg_prozent.Value = 100;

klappt es "teilweise".
Also die ProgressBar wird zwar dann bei 100% voll gefüllt. Aber das hat alles eine leichte Verzögerung. In dem Label drüber wird "100%" schon "lange" angezeigt, aber die ProgressBar ist noch nicht soweit und baut sich weiter auf, bis sie voll ist.

Also liegt es wohl an dem "Thread.Sleep()". Er stoppt dann wohl das Aufbauen der ProgressBar. Aber wieso läuft das nicht wirklich synchron mit dem Label?
In einer anderen Anwendung hab ich das aber auch so gemacht und da klappt es wunderbar.
Ich möchte halt nach dem Ablauf des Programms kurz warten und die Anwendung dann schließen, da fiel mit Thread.Sleep() als einfachste Lösung ein.

1.665 Beiträge seit 2006
vor 14 Jahren

😃

Das ist normal. Ich hab das mir fast gedacht, dass du deshalb zu dem Schluss kommst, da du die Form schließt.
Seit Vista wird die ProgressBar "animiert" gefüllt. Deswegen dauert es einen Augenblick, bis der eingegebene Wert (optisch) erreicht ist.

T
tööö Themenstarter:in
92 Beiträge seit 2006
vor 14 Jahren

Hmm...ok, das ist vielleicht eine schlüssige Erklärung. Und was kann ich dann dagegen machen, wenn ich das Programm aber danach beenden will?

Ein Setzen der ProgressBar-Eigenschaft "MarqueeAnimationSpeed" auf 0 hilft ja auch nicht. Wozu dient dann diese Eigenschaft?

1.665 Beiträge seit 2006
vor 14 Jahren

Die ist für den Style "Marquee" gedacht.. Kannst ja mal bisschen damit rumspielen.
Wenn du die 100 visuell voll erreichen willst, würde ich einen Timer starten (nach dem 100 gesetzt wurden), der nach 500ms die Form schließt.

T
tööö Themenstarter:in
92 Beiträge seit 2006
vor 14 Jahren

Und wenn ich einen Timer starte, "blockiert" er die Animation nicht so wie Thread.Sleep()?

Das wäre dann schonmal eine Lösung, ok.

Und dann noch eine letzte Frage: Dass die Animation verzögert die 100% erreicht, kann ich nicht umgehen?

1.665 Beiträge seit 2006
vor 14 Jahren

Das ist Betriebssystem Standard..
Wenn du die Form danach sowieso schließt, müsste dir das doch egal sein?!

Du kannst die Visual Styles Anwendungsweit ausschalten, aber da ist der Seiteneffekt wohl zu groß. Müsstest du also ergooglen.

T
tööö Themenstarter:in
92 Beiträge seit 2006
vor 14 Jahren

Was ist Standard? Dass er die Anwendung auch beim Timer "blockiert"?

Hrmph...ja, im Prinzip kanns mir egal sein, wenn ich die Anwendung hinterher eh schließe, aber sieht halt net so schön aus, wenn der Balken nicht ganz voll ist, aber die Anzeige zeigt "100%" an.

Oder ich warte die Zeit bis zum Schließen der Anwendung in einem anderen Backgroundworker ab, den ich im RunWorkerCompletet des ersten Backgroundworker starte. Geht das?

J
163 Beiträge seit 2007
vor 14 Jahren

Blendest du die Progressbar nach der Verarbeitung wieder aus(Visible=false)?

edit: ok, du schließt die Form.
Bei Vista und Seven ist die Progressbar so animiert . Unter XP solltest du die 100% sehen.

J
163 Beiträge seit 2007
vor 14 Jahren

Und wenn ich einen Timer starte, "blockiert" er die Animation nicht so wie Thread.Sleep()?

Das wäre dann schonmal eine Lösung, ok.

Und dann noch eine letzte Frage: Dass die Animation verzögert die 100% erreicht, kann ich nicht umgehen?

Verzögere testweise den Workerthread nach der vollständigen Abarbeitung.

T
tööö Themenstarter:in
92 Beiträge seit 2006
vor 14 Jahren

@Johnny:
Wie meinst du das? Wie soll ich den denn verzögern? Vor allem wo?

Ich hab nun einen zweiten Backgroundworker geschrieben, wie oben beschrieben. Der zweite Backgroundworker wartet nun einfach eine bestimmte Zeit und schließt dann die Anwendung.

Die Animation ist zwar verzögert, aber kann ich wohl nicht beeinflussen...außer evtl. mit seeehr viel Aufwand, aber das ist es mir bei der kleinen Anwendung nicht wert 😉

Danke für die Hilfe, wieder was dazu gelernt, was Vista und Programmierung betrifft 😉

1.665 Beiträge seit 2006
vor 14 Jahren

Was ist Standard? Dass er die Anwendung auch beim Timer "blockiert"? Dass die Windows ProgressBar ab Vista animiert ist.

Du hast doch einen konkreten Lösungsvorschlag von mir bekommen.
Starte einen System.Windows.Forms.Timer und im Tick-Event tust du ihn wieder deaktivieren (timer.Enabled = false) und schließt dort auch deine Form.

Und nein, es blockiert nichts. Der Timer ist genau dafür gedacht, nicht zu blockieren.

M
120 Beiträge seit 2009
vor 14 Jahren

Die Animation von Vista kann man umgehen, in dem man z.B. folgendes macht:

Alter Wert: 80%
Neuer Wert soll sein: 95%

Also:
Wert auf 95% setzen
Wert um 1 verringern (= Animation wird übersprungen)
Wert um 1 erhöhen
=> Wert wird auch korrekt dargestellt.