Laden...

Blockierte Threads sicher beenden

Erstellt von Ishildur vor 15 Jahren Letzter Beitrag vor 15 Jahren 5.203 Views
I
Ishildur Themenstarter:in
431 Beiträge seit 2005
vor 15 Jahren
Blockierte Threads sicher beenden

Hallo zusammen
Ich bin relativ neu in der Entwicklung von parallelen Anwendungen und habe hierzu mal eine ganz Grundlegende Frage, welche viele meiner gegenwärtigen Probleme lösen könnte:

Ich beschäftige mich gerade mit dem Problem, wie man Threads "sicher" beenden kann. Normalerweise habe ich eine bool'sche volatile Variable welche ich im Workerthread an verschiedenen Prüfe und gegenenfalls den Thread von innen heraus beende, indem ich bspw. mit break aus einer Schleife springe oder so ähnlich. Mit dieser Technik habe ich bisher sehr gute Erfahrungen gemacht, doch gibt es Fälle, wo der gesamte Thread auschliesslich eine blocking methode enthält. Ein Beispiel hierfür wäre Socket.Accept. Hier kann ich nicht eifach ein Flag prüfen, denn sobald ich Socket.Accept aufgerufen habe, geht der Programmfluss in diesem Thread nicht weiter, bis ein engehende Verbindung zustande gekommen ist. Aber bei Socket.Connect dauert es dann bis zu 30 sekunden, bis der entsprechende Thread dann auch wirklich schliesst.

Meine Frage ist nun, wie kann ich solche Threads "sicher" beenden (das heisst, sicherstellen, dass alle Resourcen freigegeben werden) ? Thread.Abort soll ja keine gute Variante sein, weil sich der ensprechende Thread zum gegebenen Zeitpunkt im finalize block befinden könnte, wodurch dieser dann nicht bis zum Ende ausgeführt wird...

Mfg Samuel

M
1.439 Beiträge seit 2005
vor 15 Jahren

=>Thread.Interrupt()

I
Ishildur Themenstarter:in
431 Beiträge seit 2005
vor 15 Jahren

Das verstehe ich jetzt nicht:
In der offiziellen Doku steht dazu folgendes:

ThreadInterruptedException wird im unterbrochenen Thread ausgelöst, jedoch erst, nachdem der Thread blockiert wurde. Wenn der Thread nie blockiert wird, wird die Ausnahme nicht ausgelöst. Daher kann der Thread möglicherweise ohne Unterbrechung abgeschlossen werden.

Also wenn ich das richtig verstehe, kann ich damit einen laufenden Thread nicht unterbrechen?

Abgesehen davon, selbst wenn es funktionieren würde, dann hätte ich doch dasselbe Problem wie bei Thread.Abort()?

Bei Thread.Abort() wird im entsprechenden Thread ThreadAbortedException und bei Thread.Interrupt() ThreadInterruptedException ausgelöst. Beides wird allerdings nicht funktionieren, wenn sich jener Thread gerade im finalize block befindet?

C
401 Beiträge seit 2007
vor 15 Jahren

Du kannst den Socket einfach mit Socket.Close() schließen und die auftretende Exception fangen und entsprechend behandeln.

I
Ishildur Themenstarter:in
431 Beiträge seit 2005
vor 15 Jahren

Hehe, du meinst, ich sollte den Socket im Aufrufenden Thread schliessen (nicht im Workerthread, welche Socket.Accept aufruft und anschliessend am warten ist?

3.971 Beiträge seit 2006
vor 15 Jahren

Ein Thread sollte sich im normal-Fall immer selbst beenden. Beispielsweise über eine boolsche Variable, die in einer Schleife geprüft wird.

Um Threads zu killen, empfiehlt es sich Thread.Abort zu verwenden. Ein Zwischending zwischen (sauber) beenden und killen gibt es nicht.

Weiterhin gibt es im .NET Framework viele Klassen, die nach dem Asynchronen Enwturfsmuster von Microsoft gehalten sind. Dort hast du entweder BeginXYZ sowie ein passendes Pendant dazu (EndXYZ) oder aber es werden dir diverse Events angeboten, die automatisch gerufen werden, wenn ein bestimmtes Ereignis eintritt (Client verbindet sich mit Socket).

Die Klasse Socket enthät beispielsweise eine Funktion BeginAccept, die ein CallBack (Delegate/Event) erwartet, das autoamtisch gerufen wird, sobald sich ein Client mit dem Socket verbunden hat. Die Funktion die BeginAccept aufgerufen hat, setzt seine arbeitet ohne warten fort.

Die Funktion EndXYZ wartet solange (hält den aktuellen Thread an), bis die Funktion BeginXYZ mit ihrer Arbeit fertig ist.

Wichtig, bei BeginXYZ, immer auch EndXYZ aufrufen. MS merkt sich, die noch offenen BeginXYZ aufrufe. Bei Anwendungen mit langer Lebensdauer, könnte das zu einem Speicherleck führen.

Das ganze nochmal zum Nachlesen/vertiefen:
Entwurfsmuster für die asynchrone Programmierung

Es gibt 3 Arten von Menschen, die die bis 3 zählen können und die, die es nicht können...

C
401 Beiträge seit 2007
vor 15 Jahren

Hehe, du meinst, ich sollte den Socket im Aufrufenden Thread schliessen (nicht im Workerthread, welche Socket.Accept aufruft und anschliessend am warten ist?

Nein, du sollst Socket.Close() vom Main Thread aus aufrufen, der Socket wird geschlossen, im Listener Thread wird ne Exception geworfen, weil er nicht auf nem geschlossenen Socket arbeiten kann und der Thread wird nach dem behandeln der Exception Ordnungsgemäß geschlossen.

Edith meint: Wer lesen kann ist im Vorteil 😃 Hattest das ja schon richtig geschrieben... Man sollte eben nicht gleichzeitig im Forum schreiben und nebenbei versuchen dem Prof zuzuhören 😄

I
Ishildur Themenstarter:in
431 Beiträge seit 2005
vor 15 Jahren

Hehe 🙂 Sitzt du auch gerade in einer Vorlesung? 😄

C
401 Beiträge seit 2007
vor 15 Jahren

Hehe 😃 Sitzt du auch gerade in einer Vorlesung? 😄

Jo, Datenbanken....

I
Ishildur Themenstarter:in
431 Beiträge seit 2005
vor 15 Jahren

Bei mir ists Stochastik 😛

I
Ishildur Themenstarter:in
431 Beiträge seit 2005
vor 15 Jahren

@marsgk
Es scheint so, als ob Thread.Interrupt() in diesem Fall nicht funktionieren würde. Kann es sein, dass Socket.Accept nicht interruptable ist?

3.971 Beiträge seit 2006
vor 15 Jahren

Kann es sein, dass Socket.Accept nicht interruptable ist?

Jupp, weil Accept solange wartet, bis sich ein Client verbindet. Die Socket-Klasse arbeitet intern mit unmanged Code, daher funktioniert Thread.Abort oder Thread.Interrupt nicht. Ein Thread.Abort oder Interrupt wird von der CLR erst verarbeitet, wenn der Thread wieder in managed Code ist.

Der Holzhammer funktioniert eben nicht immer. Deshalb gibts aber die Funktionen BeginXYZ und EndXYZ - in diesem Fall BeginAccept und EndAccept. Dort treten die Probleme nicht auf.

Es gibt 3 Arten von Menschen, die die bis 3 zählen können und die, die es nicht können...