Entwickler-Ecke

Delphi Language (Object-Pascal) / CLX - Sicherstellen, dass sich ein Thread beendet


holgerbremen - Mo 22.11.10 11:10
Titel: Sicherstellen, dass sich ein Thread beendet
Ich habe einen Thread, der alle 30 Sekunden gestartet wird, diverse Aufgaben erlegigt und sich dann beendent.

Das Beenden mache ich folgendermaßen:


Quelltext
1:
2:
   Thread.Terminate;
   Thread.WaitFor;


Ich hatte das Program nun 5 Tage durchlaufen lassen. In Logfile konnte ich sehen, dass Waitfor nach dieser Zeit nicht zurückkehrte. Der Thread beendete sich wohl nicht selbstständig. Gibts eine Möglichkeit, die zu beeinflußen bzw. den Thread nach einem Timeout selber zu killen.

Gruß
Holger


Delete - Mo 22.11.10 12:32

Mit Thread.Terminate bittest du den Thread nur sich zu beenden. Tun muss er es selber:

Delphi-Quelltext
1:
2:
3:
4:
5:
while not Terminated do
begin
  ...;
  ...;
end;


holgerbremen - Mo 22.11.10 12:53

Hi Luckie,

das ist mir schon klar. Mein Problem ist, was mache ich, wenn er sich nicht beendet. Thread.Waitfor wartet ewig und "While not Termitead" macht das gleiche.

Ich möchte den Thread nach einer Zeit x rückstandsfrei entfernen. Nur wie entferne ich ihn?


Delete - Mo 22.11.10 13:00

Anstatt an den Symptomen rumzudoktern würde ich da mal gucken, wo sich der Thread aufhängt. Auch kann es am System liegen, weil ihm die Ressourcen ausgehen oder der Thread befindet sich in einem Deadlock. Aber ohne deinen Code zu sehen, kann man da nur spekulieren.


jaenicke - Mo 22.11.10 13:05

user profile iconholgerbremen hat folgendes geschrieben Zum zitierten Posting springen:
Thread.Waitfor wartet ewig und "While not Termitead" macht das gleiche.
Dir ist aber schon klar, dass die Schleife als Beispiel für eine Arbeitsschleife für den Thread gedacht war, oder?


holgerbremen - Mo 22.11.10 13:59

Zitat:
Anstatt an den Symptomen rumzudoktern würde ich da mal gucken, wo sich der Thread aufhängt. Auch kann es am System liegen, weil ihm die Ressourcen ausgehen oder der Thread befindet sich in einem Deadlock.

Rauszufinden, wo sich der Thread aufhängt ist schwierig. Schließlich wurde er ca. 50000x gestartet und erst dann blieb er einmal hängen, was aber die Anwendung blockierte. Den Fehler zu lokalisieren ist nicht so einfach. Da er eine TCP-Verbindung aufbaut, kann der Fehler nun irgendwo liegen. Und genau aus diesem Grunde suche ich nach einer Möglichkeit, den Thread "sauber" abzuschießen, falls dieser seltene Fall auftritt.


jaenicke - Mo 22.11.10 14:00

user profile iconholgerbremen hat folgendes geschrieben Zum zitierten Posting springen:
Und genau aus diesem Grunde suche ich nach einer Möglichkeit, den Thread "sauber" abzuschießen, falls dieser seltene Fall auftritt.
Es gibt keine saubere Möglichkeit dafür. Weil das eben gerade nicht sauber ist.


platzwart - Mo 22.11.10 14:03

Abschießen ist nie sauber. Wieso musst du ihn denn unbedingt abschießen und lässt ihn nicht einfach auslaufen?


jaenicke - Mo 22.11.10 14:23

Eine der beliebtesten Möglichkeiten ist, dass du Indy benutzt und das Konzept nicht so umgesetzt hast wie es die Entwickler von Indy gerne hätten. Dabei kann man (wie ich auch gemerkt habe) böse auf die Nase fliegen.

Genauso, wenn man auf visuelle Komponenten oder Klassen zugreift, ...

Aber ohne Code wird niemand etwas genaueres dazu sagen können.


holgerbremen - Mo 22.11.10 16:09

Im Prinzip möchte bzw kann ich euch nicht wiedersprechen. Wenn sich ein Thread nicht beendet, wird es einen Grund haben. Das war aber nicht meine Ausgangsfrage.

Diese lautete: Wie kann man einen Thread sauber oder meinetwegen auch unsauber aus dem Speicher entfernen. Welche Nebenwirkungen hat z.B. "TerminateThread()". Hiermit ist es ja schließlich möglich, einen Thread zu beenden. Schließlich wird diese Funktion in der Windows-Api ja eine Daseinsberechtigung haben.


Delete - Mo 22.11.10 16:15

Belegte Ressourcen werden nicht frei gegeben. Der Referenzzähler von DLLs wird nicht zurückgesetzt. Wenn sich der Thread in einer CriticalSection befindet, kann es zu einem Deadlock kommen, weil die CriticalSection nicht verlassen wird. ...

Wir wissen, dass das nicht deine ursprüngliche Frage war, aber wir wollten dich nur darauf hinweisen, dass das keine gute Idee ist. Und langfristig wirst du dir mit TerminateThread nur mehr Probleme einhandeln.


platzwart - Mo 22.11.10 18:42

Welche Nebenwirkungen das Terminate haben kann, hast du ja selbst gemerkt. Und dir kann auf deine ursprüngliche Frage niemand eine Frage geben, weil es einfach nicht sauber geht. Und unsauber gehts so, wie du es gemacht hast...


jaenicke - Mo 22.11.10 18:46

user profile iconplatzwart hat folgendes geschrieben Zum zitierten Posting springen:
Welche Nebenwirkungen das Terminate haben kann, hast du ja selbst gemerkt. Und dir kann auf deine ursprüngliche Frage niemand eine Frage geben, weil es einfach nicht sauber geht. Und unsauber gehts so, wie du es gemacht hast...
Terminate wie er es gemacht hat ist die saubere Lösung. :gruebel:
Dabei muss der Thread natürlich auch darauf reagieren, dass Terminated True wird, und es dürfen z.B. keine Deadlocks (z.B. durch threadübergreifende Zugriffe) beim Beenden entstehen (wie es bei Indy passieren kann, wenn man nicht aufpasst).

Unsauber ist den Thread mit TerminateThread [http://msdn.microsoft.com/en-us/library/ms686717.aspx] abzuschießen.


holgerbremen - Di 23.11.10 08:55

Danke erstmal für die Hinweise, was beim Abschießen eines Threads passieren kann. Das hilft mir schon mal weiter.

Das das Killen keine saubere Lösung ist, weiß ich selber. Den Fehler habe ich auch schon gefunden, warum der Thread hing (eigener Logigfehler). Mein Problem ist nur, dass die Anwendung permanent laufen muss und ich im Falle eines Problems nicht sofort einschreiten kann. Damit alles weiterläuft, ist das Killen eines Processes wohl noch das geringste Übel. Natürlich muss ich der Ursache auf den Grund gehen.


alzaimar - Di 23.11.10 09:33

user profile iconholgerbremen hat folgendes geschrieben Zum zitierten Posting springen:
...Den Fehler habe ich auch schon gefunden...Mein Problem ist nur, dass die Anwendung permanent laufen muss und ich im Falle eines Problems nicht sofort einschreiten kann. Damit alles weiterläuft, ist das Killen eines Processes wohl noch das geringste Übel. ...

Nein. Gehe der Sache auf den Grund. Letztendlich führt kein Weg daran vorbei.
Tipp: Wechsle von den Indies zu Sockets.

Wenn ein Thread hängt, dann kann es sein, das noch nicht mal ein KillProcess etwas bringt. Du verlagerst dein Problem nur in Richtung 2011.


holgerbremen - Di 23.11.10 09:56

@alzaimar

Der Fehler lag nicht an den Indys, sondern an einer CriticalSection. Ich hatte eine Funktion verlassen, ohne die CriticalSection freizugeben. Beim nächsten Aufruf hing der Thread natürlich.

Welchen Vorteil bringen Sockets gegenüber den Indys? Ich erinnere mich noch an düstere C++ Zeiten, wo die Socketprogrammierung die Höchststrafe war.


jaenicke - Di 23.11.10 10:47

Wenn man erst einmal das Konzept hinter den Indy Komponenten verstanden hat und richtig umsetzt, funktionieren die auch gut. Ich habe leider etwas länger dafür gebraucht... jetzt bezogen auf Server mit mehreren Funktionen und so weiter...