Laden...

Schließen des (Haupt-)Fensters mit dem Beenden der Worker-Threads synchronisieren

Erstellt von partywelt vor 12 Jahren Letzter Beitrag vor 12 Jahren 1.806 Views
P
partywelt Themenstarter:in
77 Beiträge seit 2011
vor 12 Jahren
Schließen des (Haupt-)Fensters mit dem Beenden der Worker-Threads synchronisieren

Hallo zusammen,

habe ein Problem. Und zwar bastele ich ein Backupprogramm welches Dateien kopiert und mir anschließend alle Informationen in eine Datenbank schreibt.

Das ganze läuft über Threads, weil ich mehrere Kopiervorgänge gleichzeitig erlauben möchte. Wenn ich einen Auftrag abbreche, wird der Kopiervorgang abgebrochen und die entsprechenden Daten in die Datenbank eingetragen (Anzahl der Dateien, Datenmenge, Dauer usw.)

Wenn ich jedoch das Programm schließe hängt er sich bei mir immer auf. Hier mein Code den ich in das FormClosing reingepackt habe:


try
            {
                
                for (int i = 0; i < 1000; i++)
                {
                    if (Copy[i].ThreadState.ToString() == "Running")
                    {
                        Copy[i].Abort();
                        bool finish = false;
                        while (!finish)
                        {
                            finish = CancelThread(i, true);
                            MessageBox.Show(finish.ToString() + " Läuft noch");
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                Error.catchMessage(ex.Message, "FormClosing");
            }

In der Methode CancelThread werden die entsprechenden Daten in die Datenbank übertragen. In dieser Methode rufe ich mehrfach die Methode FillMethod auf, welche die Werte in einer ListView einträgt. Durch den Parameter 2 also in dem fall "true" prüfe ich ob der Thread vom Benutzer abgebrochen wurde oder das Programm geschlossen wurde. Wenn ich das Programm schließe wird der Parameter close = true übergeben und die Methode FillMethod soll nicht aufgerufen werden.

Anbei die Methode CancelThread:


private bool CancelThread(int id, bool close)
        {
            try
            {
                //mehrere Datenbankoperationen
               
                if (!close)
                {
                    FillMethod("GetListHist");
                    MessageBox.Show("Auftrag wurde durch den Benutzer abgebrochen!", "Auftrag abgebrochen", MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
                }
                return true;
            }
            catch (Exception ex)
            {
                Error.catchMessage(ex.Message, "CancelThread");
                return true;
            }

Mein Problem ist nun, dass anscheinend die Methode FillMethod trotzdem ausgeführt wird und das Programm nicht ordnungsgemäß geschlossen werden kann.

Die Fehlermeldungen der Methode lauten:> Fehlermeldung:

13.04.2012 21:12:49 Fehler: FillMethod Meldung: Auf das verworfene Objekt kann nicht zugegriffen werden.
Objektname: "Main".
13.04.2012 21:12:50 Fehler: FillMethod Meldung: Invoke oder BeginInvoke kann für ein Steuerelement erst aufgerufen werden, wenn das Fensterhandle erstellt wurde.

Was natürlich klar ist, ich frage ich aber warum die Methode überhaupt aufgerufen wird???

C
2.122 Beiträge seit 2010
vor 12 Jahren

Auf den String "Running" prüfen erscheint mir nicht schön. Prüf doch direkt auf das was da drin steht.
Hast du schon debuggt? Ich sehe nicht warum die Methode aufgerufen werden sollte. Allerdings hat CancelThread nichts mit deinem Thread zu tun, dem wird nirgends gesagt was er tun soll.

Die Messageboxen dürften auch eher verwirren, die eine führst du in einer Schleife aus.
Die wird zwar nur einmalig durchlaufen, da CancelThread immer true zurück gibt.
Einen Thread mit Abort killen ist nicht unbedingt die feine Art. Vielleicht läuft der ja doch noch eine Weile weiter, das würde das "hängen" des Programms erklären.
Dein Code macht einen ziemlich unausgereiften Eindruck. Vielleicht solltest du nochmal drüber nachdenken und das neu entwerfen.
Lies dich unbedingt in Threads ein, wie man die beendet usw.

49.485 Beiträge seit 2005
vor 12 Jahren

Hallo partywelt,

im GUI sollte man nie warten. Stoße im FormClosing das Beenden der Worker-Thread nur an und brich dann das Schließen des Fensters ab. Lass jeden Thread einen eigenen Event feuern (siehe [FAQ] Eigenen Event definieren), wenn er fertig ist. Erst wenn der letzte Thread gefeuert hat, schließe das Fenster wirklich.

herbivore

P
partywelt Themenstarter:in
77 Beiträge seit 2011
vor 12 Jahren

Tut mir leid verstehe ich nicht ... ich dachte das Ereignis FormClosing wäre dafür da Sachen zu erledigen die noch fertig gestellt werden müssen

C
2.122 Beiträge seit 2010
vor 12 Jahren

Dazu ists auch da, aber die Threads wissen davon ja nix. Vielleicht machen die da noch was längeres und lassen sich mit Abort nicht so schnell killen. Deswegen hängt die GUI.

P
partywelt Themenstarter:in
77 Beiträge seit 2011
vor 12 Jahren

Danke für eure Antworten.

Mache es jetzt anders: Werte den Thread einfach schließen ohne dass irgendwas in die Datenbank eingetragen wird. Beim Start wird eh geprüft ob noch Werte des Auftrags vorhanden sind, also wenn ich einen Auftrag Stoppe wird dieser bei der nächsten Ausführung weiter ausgeführt und so löse ich das damit auch, wenn ich das Programm schließe, dann wird beim nächsten Ausführen da weitergemacht wo ich war

1.346 Beiträge seit 2008
vor 12 Jahren

Außerdem wollte ich anmerken, dass es oftmals eher kontraproduktiv ist in mehreren Threads auf die Festplatte zuzugreifen. Dadurch muss der Lesekopf immer wieder verschoben werden. Schlussendlich ist man dann oft langsamer als wenn man die Daten nach einander lädt