AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Thema durchsuchen
Ansicht
Themen-Optionen

Threads und BackgroundWorker

Ein Thema von Luckie · begonnen am 13. Mär 2008 · letzter Beitrag vom 14. Mär 2008
Antwort Antwort
Seite 3 von 4     123 4      
Benutzerbild von Luckie
Luckie

Registriert seit: 29. Mai 2002
37.621 Beiträge
 
Delphi 2006 Professional
 
#21

Re: Threads und BackgroundWorker

  Alt 14. Mär 2008, 13:33
Das ist ein Argument. So funktioniert es:
Code:
        private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
        {
           
            for (int i = 0; i < 100000; i++)
            {
                if (backgroundWorker1.CancellationPending)
                {                   
                    e.Cancel = true;
                }
                else
                {
                    backgroundWorker1.ReportProgress((int)i / 10);
                    Thread.Sleep(0);
                }
            }
        }
Und wie breche ich einen mit der Thread-Klasse erstellten Thread ab? Abort löst eine Exception aus und Suspend lässt ihn nur pausieren. Irgendwie fehlt eine Methode zum terminieren.
Michael
Ein Teil meines Codes würde euch verunsichern.
  Mit Zitat antworten Zitat
Benutzerbild von Khabarakh
Khabarakh

Registriert seit: 18. Aug 2004
Ort: Brackenheim VS08 Pro
2.876 Beiträge
 
#22

Re: Threads und BackgroundWorker

  Alt 14. Mär 2008, 13:55
Zitat von Luckie:
Und wie breche ich einen mit der Thread-Klasse erstellten Thread ab? Abort löst eine Exception aus [...]
Wenn es eine ThreadAbortException ist, ist das goldrichtig :
Zitat:
When this method is invoked on a thread, the system throws a ThreadAbortException in the thread to abort it. ThreadAbortException is a special exception that can be caught by application code, but is re-thrown at the end of the catch block unless ResetAbort is called. ResetAbort cancels the request to abort, and prevents the ThreadAbortException from terminating the thread. Unexecuted finally blocks are executed before the thread is aborted.
Damit wird also garantiert, dass der Thread nicht einfach abgewürgt wird (was nicht gerade der BCL-Philosophie entspräche), sondern davor noch alle finally-Blöcke sauber durchlaufen werden. Mit genügend Rechten kann der Thread seinen Abbruch sogar selbst stoppen.

PS: Der Thread ist danach allerdings nicht mehr nutzbar und man benötigt einen neuen. Wenn das öfter geschehen soll, sollte man wohl besser einen ThreadPool-Thread benutzen und in diesem (wie in deinem BackgroundWorker-Code) ein Abbruch-Flag auswerten.
Sebastian
Moderator in der EE
  Mit Zitat antworten Zitat
Benutzerbild von Luckie
Luckie

Registriert seit: 29. Mai 2002
37.621 Beiträge
 
Delphi 2006 Professional
 
#23

Re: Threads und BackgroundWorker

  Alt 14. Mär 2008, 14:08
Gut, dann ist Abort doch richtig.

allerdinsg scheint nichts zu passieren:
Code:
        private void btnStop_Click(object sender, EventArgs e)
        {
            if (rbThread.Checked)
            {
                t.Abort();
            }
            else
            {
                backgroundWorker1.CancelAsync();
            }
        }
               

        private void thread1_Event(object sender, EventArgs e)
        {
            try
            {
                if (InvokeRequired)
                {
                    Invoke(new EventHandler(thread1_Event));
                }
                else
                {
                    for (int i = 0; i < 100000; i++)
                    {
                        lblStatusText.Text = resManager.GetString("ThreadStatusRunning");
                        this.Update();
                        Thread.Sleep(0);
                    }
                }
            }
            catch (ThreadAbortException tae)
            {
                lblStatusText.Text = resManager.GetString("ThreadStatusFinish");
                this.Update();
            }
        }

        private void ThreadProc()
        {
            try
            {
                thread1_Event(this, null);
            }
            catch (ThreadAbortException tae)
            {
                lblStatusText.Text = resManager.GetString("ThreadStatusFinish");
                this.Update();
            }
        }
Laut Beispiel aus der Hilfe, müsste es aber so aussehen.
Michael
Ein Teil meines Codes würde euch verunsichern.
  Mit Zitat antworten Zitat
Benutzerbild von Khabarakh
Khabarakh

Registriert seit: 18. Aug 2004
Ort: Brackenheim VS08 Pro
2.876 Beiträge
 
#24

Re: Threads und BackgroundWorker

  Alt 14. Mär 2008, 14:22
Habe ich irgendwo oben schon zu deinem ersten Thread-Code geschrieben: Du invokst thread1_Event, also wird deine gesamte Schleife im Hauptthread ausgeführt und dort kann Abort schlecht wirken. Es wird warten, bis thread1_Event beendet ist und erst dann die Exception werfen.
Sebastian
Moderator in der EE
  Mit Zitat antworten Zitat
Benutzerbild von Luckie
Luckie

Registriert seit: 29. Mai 2002
37.621 Beiträge
 
Delphi 2006 Professional
 
#25

Re: Threads und BackgroundWorker

  Alt 14. Mär 2008, 14:28
Zitat von Khabarakh:
Habe ich irgendwo oben schon zu deinem ersten Thread-Code geschrieben: Du invokst thread1_Event, also wird deine gesamte Schleife im Hauptthread ausgeführt und dort kann Abort schlecht wirken. Es wird warten, bis thread1_Event beendet ist und erst dann die Exception werfen.
Oh, dann habe ich ja gar nicht das was ich wollte. Mist. Wie mache ich es denn richtig?

Code:
private void button1_Click(object sender, EventArgs e)
        {
            if (rbThread.Checked)
            {
                try
                {
                    t = new Thread(ThreadProc);
                    t.Name = "Thead";
                    t.Start();
                }
                catch
                {

                }
            }
            else
            {
                backgroundWorker1.RunWorkerAsync();
            }
        }

        private void btnStop_Click(object sender, EventArgs e)
        {
            if (rbThread.Checked)
            {
                t.Abort();
            }
            else
            {
                backgroundWorker1.CancelAsync();
            }
        }
               

        private void thread1_Event(object sender, EventArgs e)
        {
            try
            {
                if (InvokeRequired)
                {
                    Invoke(new EventHandler(thread1_Event));
                }
                else
                {
                    for (int i = 0; i < 100000; i++)
                    {
                        lblStatusText.Text = resManager.GetString("ThreadStatusRunning");
                        this.Update();
                        Thread.Sleep(0);
                    }
                }
            }
            catch (ThreadAbortException tae)
            {
                lblStatusText.Text = resManager.GetString("ThreadStatusFinish");
                this.Update();
            }
        }

        private void ThreadProc()
        {
            try
            {
                thread1_Event(this, null);
            }
            catch (ThreadAbortException tae)
            {
                lblStatusText.Text = resManager.GetString("ThreadStatusFinish");
                this.Update();
            }
        }
Michael
Ein Teil meines Codes würde euch verunsichern.
  Mit Zitat antworten Zitat
Benutzerbild von Khabarakh
Khabarakh

Registriert seit: 18. Aug 2004
Ort: Brackenheim VS08 Pro
2.876 Beiträge
 
#26

Re: Threads und BackgroundWorker

  Alt 14. Mär 2008, 14:34
Zitat von Luckie:
Wie mache ich es denn richtig?
Wie gesagt, ist ziemlich parallel zum BackgroundWorker:
Code:
        void thread1_Event()
        {
            lblStatusText.Text = resManager.GetString("ThreadStatusRunning");
            this.Update();
            Thread.Sleep(0);
        }

        void ThreadProc()
        {
            try
            {
                for (int i = 0; i < 100000; i++)
                {
                    Invoke(new MethodInvoker(thread1_Event)); // ich kann durchaus verstehen, dass nicht jeder anonyme Methoden mag *g*
                } 
            }
            catch (ThreadAbortException tae) // hier würde ich eher finally benutzen
            {
                lblStatusText.Text = resManager.GetString("ThreadStatusFinish"); // und hier sollte es eine Cross-Call-Exception hageln
                this.Update();
            }
        }
Edit: Nach dem dritten Edit übernehme ich lieber keine Verantwortung über die Richtigkeit des Codes .
Sebastian
Moderator in der EE
  Mit Zitat antworten Zitat
Benutzerbild von Luckie
Luckie

Registriert seit: 29. Mai 2002
37.621 Beiträge
 
Delphi 2006 Professional
 
#27

Re: Threads und BackgroundWorker

  Alt 14. Mär 2008, 15:07
Jetzt schlägt allerdings die Aktualisierung im finally-Abschnitt fehl:
Zitat:
Ungültiger threadübergreifender Vorgang: Der Zugriff auf das Steuerelement lblStatusText erfolgte von einem anderen Thread als dem Thread, für den es erstellt wurde.
Michael
Ein Teil meines Codes würde euch verunsichern.
  Mit Zitat antworten Zitat
Elvis

Registriert seit: 25. Nov 2005
Ort: München
1.909 Beiträge
 
Delphi 2010 Professional
 
#28

Re: Threads und BackgroundWorker

  Alt 14. Mär 2008, 15:09
Zitat von Luckie:
Jetzt schlägt allerdings die Aktualisierung im finally-Abschnitt fehl:
Zitat:
Ungültiger threadübergreifender Vorgang: Der Zugriff auf das Steuerelement lblStatusText erfolgte von einem anderen Thread als dem Thread, für den es erstellt wurde.
Na weil da kein Invoke benutzt wurde.
Du stellst dich auch manchmal an...

Übrigens musst du nicht so umständlich mit ResourceManagern arbeiten.
Das VS erzeugt autom. statische Eigenschaften für jeden Wert in der Resource Datei, so dass du direkt auf den Namen mit dem richtigen Typ zugreifen kannst.
Robert Giesecke
I’m a great believer in “Occam’s Razor,” the principle which says:
“If you say something complicated, I’ll slit your throat.”
  Mit Zitat antworten Zitat
Benutzerbild von Luckie
Luckie

Registriert seit: 29. Mai 2002
37.621 Beiträge
 
Delphi 2006 Professional
 
#29

Re: Threads und BackgroundWorker

  Alt 14. Mär 2008, 15:22
Ich verzweifele noch mal an diesen delegate und Invoke.
Code:
private void SetStatusText(string Text)
        {
            lblStatusText.Text = Text;
            this.Update();
        }

        void ThreadProc()
        {
            try
            {
                for (int i = 0; i < 100000; i++)
                {
                    Invoke(new MethodInvoker(thread_Event));
                    Thread.Sleep(0);
                }
            }
            finally
            {
                Invoke(SetStatusText(resManager.GetString("ThreadStatusFinish")));              
            }
        }
Will er auch nicht:
Zitat:
The best overloaded method match for 'System.Windows.Forms.Control.Invoke(System.Delega te)' has some invalid arguments
Michael
Ein Teil meines Codes würde euch verunsichern.
  Mit Zitat antworten Zitat
Benutzerbild von phXql
phXql

Registriert seit: 11. Mär 2004
Ort: Mühldorf
824 Beiträge
 
#30

Re: Threads und BackgroundWorker

  Alt 14. Mär 2008, 15:37
Das Problem ist, dass SetStatusText(resManager.GetString("ThreadStatusFi nish")) kein Delegat ist. Bei deinem anderen Invoke-Aufruf hast du das ja auch zuerst in den MethodInvoker-delegaten verpackt.
Du wirst dir also wahrscheinlich für deine SetStatusText(string) einen delegaten basteln müssen, dann die Funktion darin verpacken und dann gehts.
"Dunkel die andere Seite ist"
"Yoda! Halts Maul und iss deinen Toast!"
  Mit Zitat antworten Zitat
Antwort Antwort
Seite 3 von 4     123 4      


Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 00:16 Uhr.
Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz