Laden...

thread richtig abbrechen

Erstellt von IamTheBug vor 18 Jahren Letzter Beitrag vor 17 Jahren 21.648 Views
I
IamTheBug Themenstarter:in
401 Beiträge seit 2006
vor 18 Jahren
thread richtig abbrechen

hey, wie breche ich einen thread richtig ab?
ich habe eine form für die fortschrittsanzeige und im hintergrund läuft ein thread der eine datei geöffnet hat und nun dadrauf eine zeitintensive operation ausführt.
auf der form habe ich auch einen abbrechen button, der ein thread.abort() auslöst.

das erste unschöne ist das der thread zwar abgebrochen wird aber laut doku ja nur "in der regel sofort". aber eigentlich wird der thread bei mir immer gleich abgebrochen. das problem ist nur das dann der filestream zu der datei noch auf ist und ich dann diese datei nicht löschen kann usw, da sie noch blockiert wird. gibt es so etwas wie einen thread finally block der noch ausgeführt wird, wenn der thread abgebrochen wird?
der thread arbeitet auch nicht in einer schleife so das ich bei jedem schleifendruchlauf eine bool variable abfragen kann und somit aus der schleife ausbrechen kann.
es ist halt einfach eine zeitintensieve funktion die das framework zu verfügung stellt wo ich dann nichts machen kann ausser abwarten.

Mfg

IamTheBug

S
8.746 Beiträge seit 2005
vor 18 Jahren

Original von IamTheBug
gibt es so etwas wie einen thread finally block der noch ausgeführt wird, wenn der thread abgebrochen wird?

Selbst bauen. Einfach ein großes try/catch/finally um den Inhalt deiner Thread-Routine. Ein Abort() wirft eine ThreadAbortException.

564 Beiträge seit 2006
vor 18 Jahren

Hi IAmTheBug!

Thread.Abort löst im abzubrechenden Thread eine Exception aus, welche du mit try...catch behandeln kannst und damit den Thread zu Ende führst.

Ansonsten kannst du den Abbruch besser über einen bool-Wert regeln, welchen der Thread immer wieder abfragt und weiß, ob abgebrochen werden soll oder nicht. Diese Variante fällt aber raus, wenn du die zeitintensive methode aus dem Framework nutzt, da du ja dort drin keinen Zugriff hast 😉

der Marcel

EDIT zu spät 🙂

:] 😄Der größte Fehler eines modernen Computers sitzt meist davor 😁 :]

I
IamTheBug Themenstarter:in
401 Beiträge seit 2006
vor 18 Jahren

ah gut
das mit der exception ist nicht schlecht... werde ich wohl nutzen.
gleich mal testen...

vielen dank

Mfg

IamTheBug

S
8.746 Beiträge seit 2005
vor 18 Jahren

Ich möchte mal ein Wort zu dem Abbruch-Verfahen verlieren, was hier so oft empfohlen wird: Abfragen einer Bool-Variablen.

Tatsache ist, dass dieses Verfahren in jeder Hinsicht dem Exception-Verfahren unterlegen ist, mit Ausnahme der Tatsache, dass die Exception-Generierung ein wenig mehr Zeit kostet.

Abort() befreit auch einen festgelaufenen Thread, d.h. einer der in einer Endlosschleife sitzt (andere als die Hauptschleife, wo die Variable abgefragt ist). Zudem wird der Beendigungszeitpunkt bei der Abfrage-Variante auf die Abfrage selbst beschränkt.

Die Bool-Variante bietet daher keinerlei Vorteile.

Es gibt aber auch Situationen, wo keiner der beiden Verfahren eingesetzt werden kann, nämlich wenn der Thread ereignisgesteuert läuft, also z.B. auf ein Zeichen der seriellen Schnittstelle wartet. Hier muss dann mit einem Sychronisationsobjekt der Abbruch realisiert werden, wobei WaitAny() dann sowohl auf den Abbruch-Event, als auch das eigentliche Ereignis wartet.

Thread-Abbruch also entweder über Exception oder über Sync-Objekt.

I
IamTheBug Themenstarter:in
401 Beiträge seit 2006
vor 18 Jahren

aha

vielen dank nochmal für die Erklärung. 👍 👍 👍

Und nochmal kurz was anderes was so in das Thema gehört. Wie pausiere ich den threads? Ich dachte ja erst das geht ganz einfach mit Thread.Suspend aber unter 2.0 wird das nicht mehr unterstützt. Es steht da ich soll auf thread kommunikation wie mutex und lock usw zurückgreifen...
dabei will ich doch nur auf einen button klicken. dieser soll den thread anhalten und beim erneuten klicken starten.
Ich dachte eigentlich das ginge so einfach wie. Thread.suspend() und dann thread.start() oder wie auch immer der "mach bitte weiter befehl" heisst 😁

Mfg

IamTheBug

1.373 Beiträge seit 2004
vor 18 Jahren

Man sollte sich nur bewusst sein, was Abort macht, sonst erlebt man vielleicht (nicht rekonstruierbare) böse Überraschungen.

Ich zitiere die MSDN Library:

However, if one thread calls Abort on another thread, the abort interrupts whatever code is running. There is also a chance that a static constructor could be aborted. In rare cases, this might prevent instances of that class from being created in that application domain. In the .NET Framework versions 1.0 and 1.1, there is a chance the thread could abort while a finally block is running, in which case the finally block is aborted.

Der letzte Satz ist besonders wichtig: der Thread kann auch innerhalb des finally blocks unterbrochen werden sodass Resourcen nicht freigegeben werden. (Das scheint in .NET 2.0 nicht mehr der Fall zu sein: "Unexecuted finally blocks are executed before the thread is aborted.")

Grüße,
Andre

I
IamTheBug Themenstarter:in
401 Beiträge seit 2006
vor 18 Jahren

naja ich habe ja einen try catch block der mit die threadabortexception anbfängt und das wars....

und egal an welcher stelle der code ist (er ist hauptsächlich beim langen kalkulieren einer checksumme) da kann er einfach unterbrochen werden. das juckt den restlichen code in anbetracht auf stabilität nicht. und dann greift der der catch block und die noch eventuell offenen dateien werden gechlossen.
sprich in den catch (finally) block springt er nur wenn abgebrochen wird, normalerweise rutscht er da ja gar nicht rein so das auch da innerhalb nicht abgebrochen werden kann der thread.
ISt das ungefähr das worauf du angespielt hast? oder habsch das falsch verstanden?

Mfg

IamTheBug

S
8.746 Beiträge seit 2005
vor 18 Jahren

Original von VizOne
Man sollte sich nur bewusst sein, was Abort macht, sonst erlebt man vielleicht (nicht rekonstruierbare) böse Überraschungen.

Keine Frage. Selbst die Aussage " the abort interrupts whatever code is running." stimmt ja nur insofern, dass ein Abbruch immer stattfindet, aber unklar ist wann. Bei Warteoperationen eben erst nach Beendigung derselben. Hauptursache für Thread- und damit meist auch Prozessleichen.

Daher auch die Notwendigkeit bei asynchnronen Threads mit Sync-Objekten zu arbeiten statt sich auf eine Exception zu verlassen.

Insofern sollte man Thread-Funktionalität immer soweit kapseln, dass eine Fehlbenutzung ausgeschlossen werden. Also niemals einen Thread aus einer Komponente veröffentlichen.

Threads sind eben ein kompliziertes Thema, wie Nebenläufigkeit im Allgemeinen.

S
8.746 Beiträge seit 2005
vor 18 Jahren

Original von IamTheBug
ISt das ungefähr das worauf du angespielt hast? oder habsch das falsch verstanden?

VizOne meinte u.a., dass der Finally-Block ja auch im regulären Terminierungsfall angefahren wird, aber just zu diesem Zeitpunkt die ThreadAbortException zu schlagen kann. Dann wird der Finally-Block nicht vollständig ausgeführt und Ressourcen u.a. nicht vollständig freigegeben. Denkbar wäre natürlich den finally-Block nochmal mit try/catch zu schützen und die Freigabe jeder Ressource mit Variabel zu protokollieren. Dann kann man im catch-Blöck ein "rethrow" machen, um wieder im ursprünglichen Catch/bzw. Finally-Block zu landen und dann die Ressourcen freizugeben, die es durch die Exception nicht mehr geschafft haben. Das ist so eine Art Exception-Rekursion, die erst dann beendet, wenn die Freigabe komplett durchläuft.

Ein ähnliches Verfahren kann man machen, um das Problem der statischen Konstruktoren zu lösen.

I
IamTheBug Themenstarter:in
401 Beiträge seit 2006
vor 18 Jahren

aso ich glaub ich hab jetzt verstanden was er meint.

und hast du noch einen satz zu dem pauseproblem auf lager? 🙂

Mfg

IamTheBug

S
8.746 Beiträge seit 2005
vor 18 Jahren

Seit .NET 2.0 gibt es keine explizite Methode mehr. Du musst es wirklich per Hand bauen. Ähnlich wie bei dem Abort()-Problem kann man sich sonst in Teufels Küche bringen.

Am einfachsten ist es ein ManualResetEvent verwenden, den du im signalisierten Zustand erzeugst, dann wartest du im Thread mittels WaitAny() (2. Event auf den du wartest ist der Abbruch-Event, mit Abort() kannst du hier nicht mehr sicher arbeiten, weil das System im gepausten Zustand nicht mehr mit Abort() abzubrechen ist). Da signalisiert läuft das Ding normalerweuse durch (prüfen ob Abort oder Pause!).

Wenn der Thread pausieren soll, setzt du den ManualResetEvent im Hauptthread auf nicht signalisiert (Reset()). Damit stoppt der Thread dann an der besagten Stelle. Loslaufen wieder mit Set().

564 Beiträge seit 2006
vor 18 Jahren

Hallo svenson!

Auf der anderen Seite sehe ich beim Abbrufen des Bool-Wertes als Vorteil, dass der Thread seine "letzten Angelegenheiten" selbst regeln kann und dann definiert auslaufen darf.
Wie du schon sagst, wird mit Abort aber auch eine angefangene Endlosschleife beendet, was der Abbruch per Bool-Wert nicht kann (wenn die Schleife den Bool-Wert nicht abfragt und behandelt).

der Marcel

:] 😄Der größte Fehler eines modernen Computers sitzt meist davor 😁 :]

S
8.746 Beiträge seit 2005
vor 18 Jahren

Original von der Marcel
Hallo svenson!

Auf der anderen Seite sehe ich beim Abbrufen des Bool-Wertes als Vorteil, dass der Thread seine "letzten Angelegenheiten" selbst regeln kann und dann definiert auslaufen darf.

Im Prinzip steht ja dafür der entsprechende Finally-Block bereit.

Q
6 Beiträge seit 2006
vor 18 Jahren

und hast du noch einen satz zu dem pauseproblem auf lager?

Hallo IamTheBug,
das kannst du nur mit Suspend() und Resume() machen. Früher gab es noch Sleep(x), was den Thead für x Millisekunden schlafen ließ.
Gruß

static void Main(string[] args)
        {
            Thread t = new Thread(new ThreadStart(Methode));

            t.Suspend(); // Lässt den Thread schlafen....

            t.Resume();// .... und weckt ihn wieder auf.
            
        }
S
8.746 Beiträge seit 2005
vor 18 Jahren

Ab 2.0 sind Suspend() und Resume() als obsolet gekennzeichnet. Sollte also nicht mehr verwendet werden.

I
IamTheBug Themenstarter:in
401 Beiträge seit 2006
vor 18 Jahren

ja suspend wäre die für mich jetzt eifnachste methode
aber wie schon gesagt im framework 2.0 wird das als veraltet gekennzeichnet und er compiliert das projekt auch erst gar nicht

Mfg

IamTheBug

P
992 Beiträge seit 2007
vor 17 Jahren

Hallo,

derMarcel sagt weiter oben:

"Thread.Abort löst im abzubrechenden Thread eine Exception aus, welche du mit try...catch behandeln kannst und damit den Thread zu Ende führst."

Meine frage ist jetzt, wie behandle ich diese Exception. Das Abfangen ist ja kein Problem:


try
{
     Thread tut etwas...

}
catch (ThreadAbortException eAbort)
{

}
finally
{
}

Doch was muss in catch und in finally passieren, damit der Thread ordnungsgemäß abgebrochen wird und die Excpetion nicht weitergereicht wird.

S
8.746 Beiträge seit 2005
vor 17 Jahren

Du musst die Exception nicht fangen bzw. behandeln. Das braucht es nur, wenn du Aufräumarbeiten machen willst, also z.B. irgendwas schliessen.

P
992 Beiträge seit 2007
vor 17 Jahren

Hallo svenson,

wenn ich nichts mache, dann bekomme ich beim Ausführen der exe folgende Meldung:

P
992 Beiträge seit 2007
vor 17 Jahren

Hat keiner eine Idee?

Die Anwendung funktioniert ja soweit, nur diese Meldung möchte ich gerne abfangen oder unterdrücken, bzw. den Code so gestalten, dass keine Meldung kommt.

B
1.529 Beiträge seit 2006
vor 17 Jahren

Den Post von svenson solltest du eher so verstehen, dass du nicht unbedingt Code im catch- oder finally-Block brauchst.

Also ganz außen in deiner Thread-Methode ein try-catch so wie oben um die ThreadAbortException abzufangen und innerhalb des try-Blocks dann alle IDisposable-Objekte in ein using setzen und lokale try-catch und alles läuft.

Bei der ThreadAbortException sollte man immer bedenken, dass diese für den Thread eine Exception - also Ausnahme - ist. Man sollte einen Thread nur wenn unbedingt nötig per Thread.Abort abbrechen.

P
992 Beiträge seit 2007
vor 17 Jahren

Hallo Borg,

die Meldung kommt nach wie vor. Übrigens im Debug-Modus, kommt diese Meldung nicht.

ich hab jetzt wie schon oben geschreiben einen großen Try-catch-Block in meiner Thread-Methode. Dann hab ich das eine Objekt (RichTextBox) in eine using-Anweisung gesetzt.

Was meinst du mit lokalen try-catch-Blöcken, um welche Operationen sollten noch welche gesetzt werden?

Ich rufe übrigens von meiner Funktion eine andere Funktion auf und übergebe dabei die genannte RichTextBox. Muss dabei noch etwas besonderes beachtet werden? Wenn ich in der anderen Funktion auch ein using (RichTextBox) verwende, passiert nichts mehr, da ja die RTB beim Verlassen des using-Blockes disposed wird.

T
512 Beiträge seit 2006
vor 17 Jahren

Den GUI Thread über Abort abzubrechen ist auch eine schlechte Idee. Sieht mir so aus, als ob du genau das versuchst.

Eine ThreadAbortException kann man nicht auffangen, sondern nur behandeln. Die ThreadAbortException wird automatisch sofort nach dem finally wieder gesetzt.
Dafür ists auch eine der wenigen Exceptions, die normalerweise nicht das Programm beenden, wenn sie nicht gefangen werden.

e.f.q.

Aus Falschem folgt Beliebiges

P
992 Beiträge seit 2007
vor 17 Jahren

Hallo Traumzauberbaum,

ich breche nicht den GUI-Thread ab, sondern meinen eigenen.

Meine Frage war ja, wie behandle ich die ThreadAbortException?

S
8.746 Beiträge seit 2005
vor 17 Jahren

Wenn man die ThreadAbortException nicht behandelt passiert gar nix. Da poppt nix hoch. Allenfalls im Debugger bekommst du einen entsprechenden Dialog zu sehen, weil der die ThreadAbortException per Default abfängt. Das kannst du aber in den Einstellungen von VS abschalten (was Sinn macht).

Ob du eine Behandlung machst und wie die aussieht hängt ganz allein von deinem Thread-Code ab. Insofern können wir deine Frage nicht beantworten.

P
992 Beiträge seit 2007
vor 17 Jahren

Hallo svenson,

bei mir kommt aber die weiter oben zu sehende Meldung hoch. Und zwar nur, wenn ich die exe ausführe, im Debug-Modus kommt sie nicht ...

S
8.746 Beiträge seit 2005
vor 17 Jahren

Tja, bei mir nicht. Ein Thread ohne jede Behandlung via Abort() abgeschossen terminiert einfach. Keine Meldung... nix. Egal ob als Debug oder Release compiliert. Im Debugger poppt die Exception nur noch, wenn ich ThreadAbortException in VS einschalte.

*EDIT*

Fangen geht selbst im Debugger nicht...

Lasse doch mal folgenden Code laufen und sag uns was passiert:


        static void Main(string[] args)
        {
            
            Thread x = new Thread(new ThreadStart(DoIt));
            x.Start();
            Thread.Sleep(1000);
            x.Abort();
            Console.WriteLine(\"Thread tot\");
            Console.ReadLine();

        }

        private static void DoIt()
        {
            try
            {
                while (true)
                {
                    Console.WriteLine(\"Im Thread....\");
                }
            }
            catch (ThreadAbortException)
            {
                Console.WriteLine(\"Thread wurde abgeschossen....\");
            }
        }

Sorry für die Schrägstriche, macht mein Proxy bei Anführungsstrichen...

P
992 Beiträge seit 2007
vor 17 Jahren

Mit dem von svenson angegebenen Code funktioniert es.

Das oben gezeigte Fehlerfenster kommt nicht.

Aber in meiner Anwendung tritt der Fehler nach wie vor auf.

P
992 Beiträge seit 2007
vor 17 Jahren

Um es nochmal deutlich zu sagen, in meiner Anwendung funktioniert es immer noch nicht.

Nach wie vor kommt die oben gezeigte Meldung hoch.

S
8.746 Beiträge seit 2005
vor 17 Jahren

Tja, das ist traurig, aber wie sollen wir dir helfen? Wir haben schließlich deinen Code nicht....

T
512 Beiträge seit 2006
vor 17 Jahren

Prüf mal nach, ob die Exception vieleicht von einer anderen Exception geschachtelt wird. D.h. auf unterster Ebene die Exception abfangen und selbst ausgeben.
Mehr fällt mir dazu auch nicht ein.

Erstellst du den Thread genauso wie im Beispiel? Viele Optionen hat man ja nicht...

e.f.q.

Aus Falschem folgt Beliebiges

P
992 Beiträge seit 2007
vor 17 Jahren

Hallo,

hier sind mal ein paar Codeausschnitte, vielleicht hat dann ja jemand eine Idee, wie das Problem gelöst werden könnte.

In dieser Funktion wird der Thread gestartet. Sie wird immer dann aufgerufen, wenn sich der Text einer Combobox geändert hat (OnTextChanged).


private void FillListBoxHits()
        {        
                if (tSearch != null)
                {
                    if (tSearch.IsAlive)
                    {
                        tSearch.Abort();
                        tSearch.Join();
                    }
           
                tSearch = new Thread(new ParameterizedThreadStart(SearchRTBCopy));
                tSearch.IsBackground = true;
                tSearch.Start(fsb.rtb.Rtf);
            }
        }

Die nächste Funktion ist die Funktion, die in dem Thread tSearch ausgeführt wird.


private void SearchRTBCopy(object rtf)
        {           
            try
            {
                bThreadAbort = false;
                Invoke(new MethodClearSearchAll(ClearSearchAll));            
                int iLastUpdateHitCounter = 0;
                fsb.m_iCount = 0;
                RichTextBox rtbCopy = new RichTextBox();
                using (rtbCopy)
                {
                    rtbCopy.Rtf = (string)rtf;
                    rtbCopy.WordWrap = false;
                    rtbCopy.SelectionIndent = 20;
                    string strSearch = m_strSearch;                   
                    m_iFound = rtbCopy.Find(m_strSearch, m_SearchSelStart,   m_SearchSelStart + m_SearchSelLength, m_rtbFinds);
 
                    while ((m_iFound != -1) && (!bThreadAbort))
                    {                      
                        int iLine = rtbCopy.GetLineFromCharIndex(m_iFound);
                        int iFirstChar = rtbCopy.GetFirstCharIndexFromLine(iLine);
                        int iLength = rtbCopy.Lines[iLine].Length;
                        string strText = rtbCopy.Text.Substring(iFirstChar, iLength);
                        string strTemp = strText;
                        int iNextChar = iFirstChar;
                        rtbCopy.SelectionStart = iFirstChar;
                        Color colBack = Color.White;

                        if (InvokeRequired)
                        {
                            Invoke(new MethodNextLine(NextLine));
                            Invoke(new MethodAddWord(AddWord), new Object[] { strNumber, Color.White, Color.Black });
                            Invoke(new MethodAddItem_clbHits(AddItem_clbHits), new Object[] { iLine });
                        }
  
                        while ((m_iFound != -1) && (!bThreadAbort))
                        {
                            rtbCopy.SelectionLength = 0;

                            clbAddText(rtbCopy, strText, iFirstChar, iNextChar, m_iFound, colBack, bTrim);

                            colBack = Color.LawnGreen;
                            rtbCopy.SelectionStart++;
                            clbAddText(rtbCopy, strText, iFirstChar, m_iFound, m_iFound + strSearch.Length, colBack, false);//Fundstelle hinzufügen

                            iNextChar = m_iFound + strSearch.Length;
                            colBack = Color.White;
                            if ((iLength + iFirstChar) > (m_iFound + strSearch.Length)) m_iFound = rtbCopy.Find(strSearch, iNextChar, iLength + iFirstChar, m_rtbFinds);
                            else m_iFound = -1;
          
                        }
                        if (fsb.m_iCount > iLastUpdateHitCounter + 5)
                        {
                            Invoke(new MethodUpdateHitCounter(UpdateHitCounter));
                        }
                        colBack = Color.White;
                        clbAddText(rtbCopy, strText, iFirstChar, iNextChar, strText.Length + iFirstChar, colBack, false);

                        if (iLine < rtbCopy.Lines.Length - 1)
                        {
                            iLine++;
                            //
                            if (rtbCopy.GetFirstCharIndexFromLine(iLine) < (m_SearchSelStart + m_SearchSelLength))
                            {
                                m_iFound = rtbCopy.Find(strSearch, rtbCopy.GetFirstCharIndexFromLine(iLine), m_SearchSelStart + m_SearchSelLength, m_rtbFinds);
                                if (m_iFound != -1) iLine = rtbCopy.GetLineFromCharIndex(m_iFound);
                            }
                            else
                            {
                                m_iFound = -1;

                            }
                        }
                    }
                }
                if (!bThreadAbort)
                {
                    Invoke(new MethodNextLine(NextLine));
                    Invoke(new MethodUpdateHitCounter(UpdateHitCounter));
                    Invoke(new MethodListBoxInvalidate(ListBoxInvalidate));

                }
                bThreadAbort = false;
                Invoke(new MethodAddSearchString(AddSearchString), new Object[] { m_strSearch });
            }

            catch (ThreadAbortException)
            {
            }
            
            finally
            {
                bThreadAbort = false;
            }
        }

Dann gibt es noch eine Funktion, die auch nach dem TextChanged-Ereignis aufgerufen wird. Sie sollte auch zum Anhalten des Threads dienen.


public void InterruptSearch()
        {                  
            if (tSearch != null)
            {
                bThreadAbort = true;                    
            }
        }

mfg
punkdevil

S
8.746 Beiträge seit 2005
vor 17 Jahren

Wie immer empfielt sich in solchen Situationen, Stück für Stück Code zu entfernen (auszukommentieren), bis das Verhalten stimmt.

T
512 Beiträge seit 2006
vor 17 Jahren

Ich würde mal die völlig unbasierte Vermutung in den Raum stellen, dass es was mit Invoke zu tun hat.

Du könntest mal BeginInvoke versuchen.

e.f.q.

Aus Falschem folgt Beliebiges

S
8.746 Beiträge seit 2005
vor 17 Jahren

Der Hinweis ist gut. Contro.Invoke versetzt den Thread in den Wait-State. Abort() muss ihn hingegen aufwecken. Riecht nach einem Konflikt.

P
992 Beiträge seit 2007
vor 17 Jahren

Hallo,

ich hab jetzt anscheinend das Problem gelöst.
Es wurde ja mehrfach die Funktion
clbAddText(rtbCopy, strText, iFirstChar, iNextChar, m_iFound, colBack, bTrim);
aufgerufen.

In dieser Fkt. habe ich dann mit BeginInvoke auf die GUI zugegriffen.
Statt BeginInvoke verwende ich jetzt Invoke und damit funktionierts.
Wahrscheinlich wurde, wenn Thread.Abort aufgerufen wurde, und der Aufruf in BeginInvoke noch nicht abgeschlossen war diese Exception ausgewurfen.

Besten Dank an alle Poster.

mfg
punkdevil

P
992 Beiträge seit 2007
vor 17 Jahren

Hallo,

das Problem ist doch noch nicht gelöst. Ich hatte jetzt die Funktion länger nicht verwendet und jetzt kommt die weiter oben abgebildete Meldung wieder. (ThreadAbortException).

P
992 Beiträge seit 2007
vor 17 Jahren

Nochmal meine Frage:

Ich breche den Thread folgendermaßen ab:

tSearch.Abort();
tSearch.Interrupt();
tSearch.Join();

Nach tSearch.Abort() bekomme ich eine ThreadAbortException, was ja wie ich gelsen habe auch in Ordnung ist. Doch wie verhindere ich, dass diese Exception bis an die Benutzeroberfläche durchgereicht wird (also oben gezeigte Meldung angezeigt wird)?

Wenn man bei der Meldung auf 'Weiter' klickt läuft alles wie gewünscht weiter.

49.485 Beiträge seit 2005
vor 17 Jahren

Hallo punkdevil,

ich habe nicht den ganzen Thread gelesen. Daher weiß ich nicht, ob schon gesagt wurde, das Thread.Abort nicht sinnvoll ist. Stattdessen wolltest du den Thread so programmieren, dass er sich alleine beendet, wenn z.B. eine boolsche Variable fStopThread auf true gesetzt wird. Dazu muss der Thread in der ThreadStart nur ein einfach es return machen oder ans Ende der ThreadStart-Methode kommen.

herbivore

P
992 Beiträge seit 2007
vor 17 Jahren

Hallo herbivore,

ich habe es jetzt mit einer Variable probiert.

In meiner Anwendung setze ich dazu eine Variable auf true und mache anschließend tSearch.Join(). Doch dann passiert nichts mehr.

Kann es daran liegen, das ja durch Join mein Hauptthread gestoppt wird? (Im Thread tSearch greife ich dann per Invoke auf diesen Thread zu und dadurch passiert nichts mehr)

Wie könnte man noch mitbekommen, dass ein Thread beendet wurde?

49.485 Beiträge seit 2005
vor 17 Jahren

Hallo punkdevil,

du musst die Variable in dem Thread natürlich auch abfragen. 🙂

Klar blockiert Thread.Join den Hauptthread, bis eben der extra Thread beendet wurde. Wenn die Zeit bis zum Beenden des extra Thread nicht sicher unter 1/10s bleibt, darfst du Thread.Join nicht verwenden. Stattdessen solltest du in dem extra Thread einen eigenen Event definiert wird, der gefeuert wird, wenn der extra Thread beendet ist. Im EventHandler Control.Invoke nicht vergessen, wenn du auf Controls zugreifen willst, denn der aus dem extra Thread gefeuerte Event läuft ohne weiteres Zutun natürlich in dem extra Thread.

Es gibt schon mehrere Threads zu dem Thema Thread beenden. Bitte such mal und poste die besten Treffer hier.

herbivore

P
992 Beiträge seit 2007
vor 17 Jahren

Hallo herbivore,

das Problem scheint jetzt gelöst. Wahrscheinlich hat das Abbrechen wirklich etwas länger gedauert als deine erwähnten 1/10sek.

Die letzte Anweisung in dem extra Thread ist nun das Auslösen eines Events.

Besten Dank.

Hier mal ein paar Links aus dem Forum zum Beenden von Threads:

Probleme beim Thread beeden
Thread abbrechen die 2.te
Thread, der nach Programmende noch lebt
[Threading] Problem beim Beenden eines Thread
asynchroner Thread beendet oder nicht? Wie prüfen?
Threading
Thread killen