Thread + Maske im Hintergrund

Marc79

Mitglied
Hallo zusammen,

anbei eine kurze Frage zum folgenden Problem.

ToDo:
Es sollen Dateien von a nach b kopiert werden
Es soll eine Progressbar angezeigt werden
Es sollen die einzelnen Kopierschritte in einer Listbox ausgegeben werden

Idee:
Der Kopiervorgang muss in einem Thread ausgelagert werden
Die anzuzeigenden Steuerelemente werden ivoked

Quellcode:

-> Diese Methode wird irgendwann mal aufgerufen.
Code:
public void runThread()
{
            t = new Thread(new ThreadStart(start));
            t.Start();
            progMain.Maximum = main.listBoxFiles.CheckedItems.Count;
            progMain.Minimum = 0;
}

-> In der Start-Methode wird geprüft, ob ein Invoke notwendig ist
Code:
public void start()
{
            if (this.InvokeRequired)
            {
                this.Invoke(new MethodInvoker(start));
                return;
            } 

     [... Irrelevanter Code ...]

    // Irgendwann werden hier die Update-Methoden aufgerufen
    mainProgressbar();
    updateListbox("irgendeintext");

    [... Irrelevanter Code ...]
}

-> Die Methoden für den Update

Code:
private void updateListbox(string value)
{
            list.Items.Add(value);
            list.Update();
}

private void mainProgressbar()
{
            progMain.Value++;
            progMain.Update();
 }

Ergebnis:
Grundsätzlich läuft das alles wunderbar.
ProgressBar wird upgedatet und die Listbox erhält ihre Schritte.

Problem:
Wehe das Fenster verliert den Fokus -> Man klickt z.B. ein anderes Fenster in den Vordergrund oder wechselt mal die Applikation. Ab diesem Zeitpunkt werden die Fortschritte nicht mehr angezeigt. Erst wenn die Applikation komplett ferig ist, werden die Änderungen dargestellt.

Was mache ich falsch? Was muss ich ändern oder beachten?

Vielen Dank euch vorab,
Gruß Marc
 
Ruf mal zusätzlich vor "Update()" noch "Invalidate()" des Progressbar auf. Denn zu "Update" steht in der Doku

Causes the control to redraw the invalidated regions within its client area.

Aber du hast ja nichts invalidiert. Ist aber nur ne Vermutung.
 
Ich denke die richtige Lösung ist, das Invoke nur für das Aktualisieren der Progressbar zu verwenden, nicht aber für die Start-Methode. Denn so wie du es momentan machst, passiert Folgendes:
  1. Der Hauptthread A erstellt einen neuen Thread B
  2. Neu erstellter Thread B startet Methode "Start"
  3. Methode "Start" stellt fest, dass sie nicht auf dem Hauptthread A läuft. Daraufhin beendet sie sich in Thread B und startet sich neu in Thread A!
Effektiv gesehen hast du keinen zweiten Thread erstellt. Alles wird in A bearbeitet.
Was du aber wirklich willst, ist, dass "start" von Thread B bearbeitet wird, lediglich die Aufrufe zum Aktualisieren der Fortschrittsanzeige sollen per Invoke von Thread A bearbeitet werden. Die InvokeRequired-Prüfung gehört damit z.B. in die Methoden "updateListbox" und "mainProgressbar", anstatt in "start".
 
Zuletzt bearbeitet:
Danke für den Hinweis!
Das löste zwar das Problem mit dem "Einfrieren" nicht ganz wirklich, aber technisch gesehen ist es nun auf jeden Fall sauber!
 

Neue Beiträge

Zurück