Entwickler-Ecke

Sonstiges (.NET) - ThreadAbortException


georgeboy - Do 01.07.21 15:35
Titel: ThreadAbortException
Hallo zusammen, ich lese schon die ganze Zeit, kann das Problem nicht lösen. Einen Sekundär-Thread kann man von aussen mit myThread.Abort() beenden. In der Thread-Funktion kann man "ThreadAbortException" mit try-catch abfangen. Wenn innerhalb des try-Blocks umfangreicher Code steht, weiss man doch nicht, an welcher Stelle das ThreadAbortException aufgetreten ist, und man weiss doch nicht welche Aufräumarbeiten zu machen sind. Da verstehe ich wohl irgendetwas nicht. Weiss jemand Rat ?

Moderiert von user profile iconTh69: Topic aus WinForms verschoben am Do 01.07.2021 um 16:13


Th69 - Do 01.07.21 16:09

Hallo,

Thread.Abort ist veraltet und sollte nicht (mehr) benutzt werden: Thread.Abort ist veraltet [https://docs.microsoft.com/de-de/dotnet/core/compatibility/core-libraries/5.0/thread-abort-obsolete] (aber auch schon vorher im .NET Framework 4.x, nicht erst seit .NET 5). Umbau steht unter "Empfohlene Maßnahme".


Ralf Jansen - Do 01.07.21 16:14

Du mußt deinen Code schon so schreiben das du am Ende des Threads, egal ob erfolgreich, nicht erfolgreich oder abgebrochen, weißt was noch aufzuräumen ist.

Das ändert sich auch nicht durch das Verfahren egal ob man klassisches Thread mit Abort oder Tasks mit CancellationTokens verwendet.

Edit: Es hilft oft disposable Klassen auch passend zu benutzen (mit einem passenden using) dann erledigt sich das meiste Aufräumen von alleine.
Bei Dinge die anders freigegeben werden müssen hilft es zu überlegen ob die nicht durch eine eigene Klasse die IDisposable implementiert geschachtelt werden können.


georgeboy - Fr 02.07.21 07:47

Dann gibt es noch die Lösung mit der globalen Bool-Variablen "SollAbgebrochenWerden". Und im aufrufenden Code:


C#-Quelltext
1:
2:
SollAbgebrochenWerden = true;
myThread.Join();


Spricht etwas dagegen ?


Th69 - Fr 02.07.21 09:13

Kommt drauf an, wie und wo du diese deklariert hast (globale Variablen gibt es ja nicht in C#).


georgeboy - Fr 02.07.21 13:53

Oben in der gleichen Klasse, in der die Thread-Funktion enthalten ist. "Global" bzgl der Klasse. oder "Klassenmember" ?


C#-Quelltext
1:
2:
3:
4:
5:
6:
// class ...
volatile bool SollAbgebrochenWerden;
// ... 
// SollAbgebrochenWerden = false;
// myThread.Start();
// ...


Th69 - Fr 02.07.21 14:19

Ja, das geht so. Du mußt diese dann aber periodisch in deiner Thread-Methode abfragen. Wenn du aber intern z.B. eine blockierende Methode hast, dann nützt dir dies nichts.

Eine andere Möglichkeit wäre z.B. ein WaitHandle o.ä., s. My two cents on the Thread.Abort and Thread.Interrupt methods [https://www.infoworld.com/article/3105821/my-two-cents-on-the-thread-abort-and-thread-interrupt-methods.html] (letzter Abschnitt) sowie auch Abbruch in verwalteten Threads [https://docs.microsoft.com/de-de/dotnet/standard/threading/cancellation-in-managed-threads] ("Lauschen mithilfe eines Wait-Handles").


Ralf Jansen - Fr 02.07.21 14:52

Thread.Join wird nur eher schwierig wenn du das von deinem Hauptthread aus machst.
Join hält den Thread an bis der andere fertig.

Aus diesem Thread dann eine UI zu zeichnen (wir kamen ja aus dem WinForms Subforum) oder den boolean zu setzen geht nicht.


georgeboy - Fr 02.07.21 14:59

Wenn man im Haupt-Thread sagt SollAbgebrochenWerden = true; und die Abfragen in der Thread-Funktion:
if ( SollAbgebrochenWerden ) ... geschickt gesetzt sind, braucht der Sekundär-Thread nicht lange bis er terminiert.


georgeboy - Fr 02.07.21 15:47

Dann, Dankeschön Euch !!!