Laden...

[gelöst] - Warum wird ToolStripProgressBar nicht sichtbar trotz setzen des Visible-Properties?

Erstellt von ChrisProg vor 3 Jahren Letzter Beitrag vor 3 Jahren 1.966 Views
ChrisProg Themenstarter:in
174 Beiträge seit 2009
vor 3 Jahren
[gelöst] - Warum wird ToolStripProgressBar nicht sichtbar trotz setzen des Visible-Properties?

Hallo,

folgendes Problem:

Ich habe eine Form mit einem StatusStrip, auf dem ein TollStripStatusLabel und eine TollStripProgressBar sind.

Die ProgressBar ist folgendermaßen voreingestellt:


            this.toolStripProgressBar.Name = "toolStripProgressBar";
            this.toolStripProgressBar.Size = new System.Drawing.Size(40, 16);
            this.toolStripProgressBar.Style = System.Windows.Forms.ProgressBarStyle.Continuous;
            this.toolStripProgressBar.Visible = false;

(Maximum steht auf 100 / Minimum auf 0 ...)

Die ProgressBar soll nur bei Bedarf aufgerufen werden.

Um dies zu realisieren habe ich eine Methode geschrieben die je nach Bedarf einen invoke durchführt oder aber direkt mit der ProgressBar "spricht"

        
        public void SetProgressBar(Boolean xx_aktiv = false)
        {
            try
            {
                if (this.statusStrip1.InvokeRequired)
                {
                    this.statusStrip1.Invoke(new MethodInvoker(() => this.toolStripProgressBar.Visible = xx_aktiv));
                    this.statusStrip1.Invoke(new MethodInvoker(() => this.statusStrip1.Refresh()));
                }
                else
                {
                    this.toolStripProgressBar.Visible = xx_aktiv;
                    this.statusStrip1.Refresh();
                }
            }
            catch (Exception ex) { }
        }


Nun zu meinem Problem:
die ProgressBar wird nicht sichtbar 🤔 - egal, ob ich das direkt oder in einem BgWorker mache.

Wenn ich durch steppe, so sehe ich das die Eigenschaft zwar auf Visible = true gesetzt wurde, aber es passiert nichts ...

Wenn ich aber die Eigenschaft Visible in den Form-Eigenschaften auf true stelle, dann sehe ich die ProgressBar, sobald die Maske angezeigt wird (was ich ja nicht will...).

Kann mir das bitte mal jemand plausibel erklären ?

MfG ChrisProg

16.806 Beiträge seit 2008
vor 3 Jahren

Ich würde fast wetten er läuft in den catch und Du bemerkst es nicht, weil das try/catch so einfach sinnlos und quatsch ist 😉

Mach es wie [FAQ] Controls von Thread aktualisieren lassen (Control.Invoke/Dispatcher.Invoke) es vorsieht.

ChrisProg Themenstarter:in
174 Beiträge seit 2009
vor 3 Jahren

Hallo Abt,

das ist es nicht, denn wie ich schrieb "Wenn ich durch steppe, so sehe ich das die Eigenschaft zwar auf Visible = true gesetzt wurde, aber es passiert nichts ..." - er geht nicht in eine Exception...

"weil das try/catch so einfach sinnlos und quatsch ist" - meinst Du das generell, oder für diesen Fall ?

Wenn generell, bitte erklären ...
(wenn in diesem Fall, hast Du wohl recht, das ist noch übrig geblieben vom Start-Code - aber schaden tuts ja auch nicht, oder?)

MfG ChrisProg

87 Beiträge seit 2016
vor 3 Jahren

Hallo,

du fängst die Exception, behandelst sie aber nicht.

glandorf

ChrisProg Themenstarter:in
174 Beiträge seit 2009
vor 3 Jahren

Das ist mir schon klar u. soll auch so sein...

Es geht hier ja "nur" um eine Anzeige für den User (also nichts wichtiges) - wenn es, warum auch immer, hier zu einem Fehler kommen sollte, dann soll dadurch nicht das Programm behindert werden ...

MfG ChrisProg

W
955 Beiträge seit 2010
vor 3 Jahren

Die Leute meinen du sollst die Exception richtig behandeln damit du erfährst was der Fehler ist. Mach da wenigstens ein Breakpoint ran.

ChrisProg Themenstarter:in
174 Beiträge seit 2009
vor 3 Jahren

Nochmal: das ist nicht mein Problem ! er geht in keine Exception !!!

Im Anhang des Screenshots im Debug-Modus (vor dem setzen):
(eingefühte IMGs werden leider nicht akzeptiert...)

er führt die Befehle aus, die Progressbar wird aber trotzdem nicht sichtbar ...

Was ich aber vergessen habe zu erwähnen:
Der StatusStrip sitzt auf einer vererbten Form, auch der hier gezeigte Quellcode ist in der vererbten Form, der Aufruf erfolgt in der "Unterform" mit

SetProgressBar(true);

Was aber meiner Meinung nach kein Problem darstellen sollte, oder ?

Es funktionert nur, wenn ich die ProgressBar in der Entwicklungsumgebung auf Visible = true setzte !
Dann muss ich es aber im im Form-Aufruf nach InitializeComponent() wieder auf

toolStripProgressBar.Visible = false;

setzen, was ich aber eigentlich nicht will (--> mögliches "flackern"...)

MfG ChrisProg

ChrisProg Themenstarter:in
174 Beiträge seit 2009
vor 3 Jahren

hier der nächste Schreenshot nach dem Steps ...

4.931 Beiträge seit 2008
vor 3 Jahren

Ich tippe auf [FAQ] Warum blockiert mein GUI?

Wieso wird hier überhaupt Invoke aufgerufen, d.h. rufst du SetProgressBar(true) aus einem anderen Thread heraus aus?

ChrisProg Themenstarter:in
174 Beiträge seit 2009
vor 3 Jahren

Das war auch zuerst meine Vermutung, deshalb habe ich mir den Artikel durchgelesen - aber: die Aktionen sind keinesfalls "langlaufend".

Dagegen spricht auch, das alles funktioniert, wenn man die ProgressBar beim Initialize schon auf Visible = true hat (und dann direkt wieder auf Visible = false setzt) ...

Und ja, da die eigentliche Codeausführung (Upload von Dateien) länger dauern kann, wird das ganze aus einem BgWorker heraus (gleich zu Beginn) aufgerufen ...

Die ProgressBar soll dabei den Fortschritt anzeigen.

MfG ChrisPorg

4.931 Beiträge seit 2008
vor 3 Jahren

Und die Form ist auch aktiv und bedienbar?
Oder blockierst du in einem der Form-Ereignisse den weiteren Ablauf?

PS: Beim BackgroundWorker gibt es das ProgressChanged-Ereignis (das im UI-Thread läuft, so daß kein eigenes Invoke mehr nötig ist).

Außerdem kann man die gesamte Funktionalität besser mit asynchroner Programmierung umsetzen.

16.806 Beiträge seit 2008
vor 3 Jahren

Mach es ordentlich mit async/await, wie in dem bereits geposteten Link.
Wenn Du es so nicht machen willst, dann musst halt mit Fehlern leben 🤔

ChrisProg Themenstarter:in
174 Beiträge seit 2009
vor 3 Jahren

@Th69:
Ich hab mal ein System.Threading.Thread.Sleep(15000); eingebaut um das zu testen - Ja, die Form ist aktiv (lässt sich verschieben) und bedienbar (Klick auf Abbrechen-Button wird ausgeführt) ...

Das mit ProgressChanged kann hier doch noch gar nicht greifen, ich will doch erst einmal die ProgressBar sichtbar machen...

"Außerdem kann man die gesamte Funktionalität besser mit asynchroner Programmierung umsetzen." - dabei könnte ich aber dem User nicht zeigen, wie weit die Datei ist (außer ich würde für jede Datei eine ProgressBar erstellen) ...

Und, ich sehe im massenhaften parallelen Upload ein Performance-Problem (alleine schon durch die Bandbreite ...)

@Abt:
Es liegt nicht am BGWorker - wenn ich


SetProgressBar(true);

aus der Form direkt aufrufe, dann durchläuft er die "else"-Schleife , steht wieder die Eigenschaft richtig, aber es wird nicht angezeigt ...

Ich werde halt damit leben müssen, das ich die ProgressBar in der Entwicklung auf visible=true und dann direkt beim Aufruf wieder auf visible = false setzten muß - nur verstehen tue ich das nicht ...

MfG ChrisProg

16.806 Beiträge seit 2008
vor 3 Jahren

Ja, das Verhalten ist auch korrekt.
Wenn Dich das wundert, wenn fehlen Dir hier einfach die Basics von Forms und Co.

Aber gut; die Leute versuchen Dir hier zu helfen und Du magst Dich mit Händen und Füßen wehren.
Da kann man halt nichts machen.

ChrisProg Themenstarter:in
174 Beiträge seit 2009
vor 3 Jahren

@Abt:
ich bin weiß Gott nicht allwissend und weit davon entfernt perfekt zu sein, aber die Antwort finde ich doch etwas herablassend ...

Wenn Du es weißt, wäre es dann nicht besser, andere an deinem Wissen teil haben zu lassen ?

Mittlerweile weiß ich, was passiert (Bug?):

der StatusStrip steht auf AllowMerge = true, in ihm sind zwei Objekte enthalten:

  • ein StatusStripText welches Spring = true und AutoSize = false eingestellt ist
  • eine ProgressBar welche auf Visible = false ist

Wenn ich nun die Form starte und die Größe(Breite) ändere, dann passt sich der StatusStripText entsprechend an (wie erwartet).

Gem Microsoft Docs bedeutet Spring:

Eigenschaftswert
Boolean
true, wenn ToolStripStatusLabel beim Ändern der Größe des Formulars automatisch den verfügbaren Leerraum von StatusStrip füllt; andernfalls false. Der Standardwert lautet false.

Nach meinem Verständnis würde das bedeuten, das wenn ein anderes Objekt hinzukommt, der verfügbare Leerraum kleiner wird u. dementsprechend auch der StatusStripText kleiner werden müsste - dem ist aber nicht so !

Wenn man nun, nachdem man die ProgressBar programmatisch auf Visible = true gesetzt hat, die Form langsam (so das der Rechner das noch zeichnen kann) in der Breite verändert, passiert immer noch nichts - wenn man das aber ruckartig macht, erscheint plötzlich die ProgressBar ...

Die Eigenschaft AutoSize des StatusStripTextes ist der entscheindende Wert - ich hatte ihn auf false gestellt, da ich glaubte, das das zusammen mit Spring nicht sauber funktionieren würde (doppelt gemoppelt)...

Aber: wenn ich AutoSize auf true stelle, dann funktioniert es sofort - ist für mich nicht wirklich nachvollziehbar, aber es ist so ...

Du siehst: es hatte wirklich nichts mit Threading zu tun ...

Ich wehre mich bestimmt nicht gegen Hilfe und bin dafür auch dankbar (so bin ich auch dankbar für den Hinweis auf asynchrone Programmierung, die bisher noch nicht auf meinem Radar war (in VFP gänzlich unbekannt...) - aber ich werde mich da mal einlesen...)

MfG ChrisProg

16.806 Beiträge seit 2008
vor 3 Jahren

Immer schwierig vernünftig zu reden, wenn man Kritik immer als herablassend aufnimmt.
Aber gut; so ist die Gesellschaft halt...

Wenn Du es weißt, wäre es dann nicht besser, andere an deinem Wissen teil haben zu lassen ?

Mehrfach wurdest Du nun auf asynchroner Programmierung hingewiesen; dass das der bessere Weg ist.
Direkt und über den Hinweis auf die Artikel in der FAQ, die selbiges (mit Grund) aussagen.

Wenn Du also immer noch nach "Wissen" fragst, dann zeigt mir das zwei Dinge:

  • Du hast die entsprechenden Stellen einfach überlesen
  • Du ignorierst die Hinweise

Beide Fälle sind halt nicht zielführend und Grundlage meiner Aussage.

Ein Minimalstbeispiel (respektive [Tutorial] Vertrackte Fehler durch Vergleich von echtem Projekt mit minimalem Testprojekt finden ) kann so aussehen, funktioniert einwandfrei.

public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();

            toolStripProgressBar1.Visible = false;
        }

        private async void button1_Click(object sender, EventArgs e)
        {
            await RunStatus();
        }

        public async Task RunStatus()
        {
            toolStripProgressBar1.Visible = true;
            toolStripProgressBar1.Value = 0;

            
            while (toolStripProgressBar1.Value < 100)
            {
                toolStripProgressBar1.Value += 1;

                await Task.Delay(100);
            }

            toolStripProgressBar1.Visible = false;
        }
    }
ChrisProg Themenstarter:in
174 Beiträge seit 2009
vor 3 Jahren

Hallo @Abt,

Danke !

Nur zum Verständnis:
Wenn ich deinem Bespiel folge, dann kann (sollte) ich ja im Prinzip alles was ich Auslöse mit async / await machen, oder würdest Du das auch machen, wenn tatsächlich "nur" visible gesetzt würde und das "füllen" an anderer Stelle passiert (und dann das "füllen" mit async /await machen)?

Macht dieses Vorgehen dann den BgWorker nicht gänzlich überflüssig?

Zu meinem tatsächlichen Problem:
Ist das denn für Dich nachvollziehbar, das ich zusätzlich zum Spring auch das Autosize auf true gesetzt haben muss, oder ist das tatsächlich ein Bug?

P.S.: kann man hier irgendwie einen Beitrag als gelöst / erledigt markieren ?

MfG ChrisProg

16.806 Beiträge seit 2008
vor 3 Jahren

alles was ich Auslöse mit async / await machen,

Verwende async/await wo sinnvoll, nicht überall.

Macht dieses Vorgehen dann den BgWorker nicht gänzlich überflüssig?

Wow. Richtig!

Aber: wenn Du den verlinkten Artikel gelesen hättest, dann hättest Du bereits gelesen, dass der BGW in die Mottenkiste gehört und fast alles mit async/await gelöst werden kann.
Ebenso hat das Th69 bereits inhaltlich ausgedrückt => asynchrone Programmierung.

Das ist genau das was ich meine....

P.S.: kann man hier irgendwie einen Beitrag als gelöst / erledigt markieren ?

[Hinweis] Wie poste ich richtig?