Laden...

Wegen blockierendem GUI foreach in Thread auslagern

Erstellt von simons vor 15 Jahren Letzter Beitrag vor 15 Jahren 1.155 Views
S
simons Themenstarter:in
29 Beiträge seit 2008
vor 15 Jahren
Wegen blockierendem GUI foreach in Thread auslagern

Guten Tag

Ich habe bis jetzt noch nie Threads gearbeitet, jedoch komme ich nun bei folgendem Problem wohl ohne einen Thread nicht aus..

Ich muss mit meinem Programm ResxFile "aufräumen".

Hier mein Problem:

private void btnCleanUp_Click(object sender, EventArgs e)
{
canceled = false;

// Button CleanUp enablen
btnCleanUp.Enabled = false;

// Button Abbrechen einblenden
btnAbbrechen.Visible = true;

foreach(ListViewItem item in lsvFiles.Items)
            {
                // Überprüfen ob abgebrochen wurde
                if (canceled)
                    // dann brechen wir ab
                    break;

                // Überprüfen ob wir ein Objekt haben
                if (item.Tag == null)
                    continue;

                // RESXFile aus Tag holen
                RESXFile resxFile = item.Tag as RESXFile;
                // Wir cleanen das File
                resxFile.ChangeResx();
            }

            // Button CleanUp wieder enablen
            btnCleanUp.Enabled = true;

            // Button Abbrechen ausblenden
            btnAbbrechen.Visible = false;
}

So sieht die Aufräum-Aktion momentan aus. Das GUI ist so natürlich blockiert und der Abbrech-Button kann nun nicht mehr angeklickt werden. Nun habe ich gelesen, dass ich das mit einem Thread lösen könnte.

Ich habe schon lange gegooglet und auch hier die Suche verwendet. Habe aber nie eine Beispiel gefunden wie ich es lösen könnte.

So viel ich verstanden habe, müsste ich die foreach-Schlaufe in einen Thread auslagern, aber mein Problem liegt da bei der Umsetzung.. Hoffe ihr könnt mir da irgendwie weiterhelfen.

Besten Dank und einen schönen Abend
Gruss
Simon

467 Beiträge seit 2007
vor 15 Jahren

ich hoffe(wie immer) das ist kein Mist, aber ich würde die Methode mit Invoke aufrufen(edit: das heißt, die foreachschleife in eine eigene Methode packen diese mit invoke aus dem Handler aufrufen), und dann (nicht das sellbe) mii Invoke auf die Controls zugreifen.

49.485 Beiträge seit 2005
vor 15 Jahren

Hallo simons,

Ich habe schon lange gegooglet und auch hier die Suche verwendet. Habe aber nie eine Beispiel gefunden wie ich es lösen könnte.

steht sogar in der FAQ [FAQ] Warum blockiert mein GUI? inkl. Link zu einem Beispiel.

herbivore

467 Beiträge seit 2007
vor 15 Jahren

ich merke gerade, dass ich es auch vergessen habe. Länger nichts mehr mit WINForms gemacht, und dieses Invoke eig. nie gebraucht.

        private void button1_Click(object sender, EventArgs e)
        {
            Thread T = new Thread(new ThreadStart(DOLOOP));
            T.Start();
        }

        void DOLOOP()
        {
            if (this.InvokeRequired)
                this.Invoke(new MethodInvoker( DOLOOP));
            Thread.Sleep(3000);
            button1.Enabled = false;
                //...
        }

Ich dachte, das müsste funktionieren, aber die GUI bleibt trotzdem stecken. Was ist denn da falsch?

49.485 Beiträge seit 2005
vor 15 Jahren

Hallo ANSI_code,

siehe [FAQ] Warum blockiert mein GUI? Abschnitt "Achtung: Die Falle"

herbivore

S
simons Themenstarter:in
29 Beiträge seit 2008
vor 15 Jahren

Hallo simons,

Ich habe schon lange gegooglet und auch hier die Suche verwendet. Habe aber nie eine Beispiel gefunden wie ich es lösen könnte.
steht sogar in der FAQ
>
inkl. Link zu einem Beispiel.

herbivore

Besten Dank euch beiden. Habe diese Seite schon mal gesehen und es so versucht. Funktionierte damals jedoch leider nicht. Nun habe ich es noch einmal versucht und so sieht es aus:

private void btnCleanUp_Click(object sender, EventArgs e)
{
            canceled = false;

            // Button CleanUp enablen
            btnCleanUp.Enabled = false;

            // Button Abbrechen einblenden
            btnAbbrechen.Visible = true;

            this.Invoke(new MethodInvoker(CleanUp));

            // Button CleanUp wieder enablen
            btnCleanUp.Enabled = true;

            // Button Abbrechen ausblenden
            btnAbbrechen.Visible = false;
}

private void CleanUp()
        {
            foreach (ListViewItem item in lsvFiles.Items)
            {
                // Überprüfen ob abgebrochen wurde
                if (canceled)
                    // dann brechen wir ab
                    break;

                // Überprüfen ob wir ein Objekt haben
                if (item.Tag == null)
                    continue;

                // RESXFile aus Tag holen
                RESXFile resxFile = item.Tag as RESXFile;
                // Wir cleanen das File
                resxFile.ChangeResx();

                Application.DoEvents();
            }
        }

Ich habe dieses mal noch Application.DoEvents() in der Invoke-Methode eingefügt und nun funktioniert es eigentlich.

Ist das so auch eine saubere Lösung?

467 Beiträge seit 2007
vor 15 Jahren

@herbivore: Man bin ich blöd 😁 Das ist ja völliger Käse alles wieder zurückzuverlagern! Das hätte mir auch ohne den FAQ Thread klar sein müssen. Ich glaub ich geh dann ins Bett. So kann ich nicht progen(mit Hirn:off)

@simons
gewöhndir das DoEvents aber nciht an, das ist nich so toll.

49.485 Beiträge seit 2005
vor 15 Jahren

Hallo simons,

Ist das so auch eine saubere Lösung?

in deinem konkreten Fall zumindest eine recht einfache. Ansonsten schätze ich DoEvents nicht. Auf DoEvents wird ja in [FAQ] Warum blockiert mein GUI? doch recht ausführlich eingegangen.

herbivore

S
simons Themenstarter:in
29 Beiträge seit 2008
vor 15 Jahren

ok besten dank für eure Hilfe.

Wenn jedoch jemand mir die saubere Lösung dafür hat bin ich auch nicht gerade abgeneigt, da ich wohl einen Thread auch noch bei dem Suchen der Files verwenden sollte..

S
142 Beiträge seit 2007
vor 15 Jahren

Hallo simons,

Schau Dir doch mal die Klasse Backgroundworker an...
http://www.harrys-pcshop.at/visual_csharp/visual_csharp_19_015.htm#Xxxobkap1901504001a5e1f02c186

Ist nicht immer angebracht, kann aber in manchen Situationen einer "Threadabgeneigten" Person die Arbeit mit Threads abnehmen.

Vom technischen Hintergrund kommt das in Etwa aufs Selbe hinaus, abgesehen davon, dass hier ein bestehender Thread aus dem Threadpool verwendet wird anstatt einen neuen zu erstellen.

mfg Steave