Wie beende ich ein Multithread-Programm?

8

Ich habe gerade mit Threading in Python herumgespielt, schrieb dieses grundlegende IM-Ding [Code unten]

Ich habe bemerkt, dass wenn ich das Programm mit C-c beende, es nicht beendet wird, es hängt einfach für immer.

Ich vermute nur, dass es darauf wartet, dass jeder Thread beendet, was sie tun, aber da es eine Endlosschleife ist, die niemals passieren wird.
Ich denke, ich muss jeden Faden manuell töten oder die Schleife beenden, wenn das Killsignal kommt.
Wie würde ich das tun?

%Vor%     
Steinthor.palsson 01.05.2011, 15:55
quelle

2 Antworten

7

Ich sehe mehrere Ursachen für das Fehlverhalten in Ihrem Code.

  1. Strg + C verursacht eine "KeyboardInterrupt" -Ausnahme im Haupt-Thread. Du solltest damit umgehen.
  2. Ihr Socket befindet sich im Sperrmodus. Dies bewirkt, dass mehrere Socket-Funktionen den aufrufenden Thread blockieren, bis die Funktion zurückkehrt. Während dieses Status kann der Thread nicht auf ein Beendigungsereignis reagieren.
  3. Wie Sie bereits gesagt haben: Ihre endlose Schleife in der Funktion run () des Threads ist ... wirklich endlos. Die Ausführung des Threads endet also nie (zumindest nicht ohne eine unerwartete Ausnahme). Sie sollten eine Art von Synchronisationsobjekt verwenden, z. B. ein threading.Event-Objekt, um einem Thread extern mitzuteilen, dass er sich selbst beenden soll.
  4. Ich würde von der Verwendung von raw_input () aus dem Hauptthread abraten. Stellen Sie sich vor, was passiert, wenn Sie mehr als einen Shout-Thread haben.
  5. Warum schließen und verbinden Sie den Socket immer wieder, wenn eine Nachricht in Ihrer Shout-Klasse übertragen wurde? Netzwerkverbindungen sollten wegen der Einrichtungskosten nur in speziellen Fällen wiederhergestellt werden.
  6. Ohne ein Frame-Protokoll für die Kommunikation können Sie nicht erwarten, dass alle Daten empfangen wurden, die vom anderen Host gesendet wurden, wenn die Funktion recv () zurückkehrt.
  7. Die Funktion start () des Thread-Objekts gibt keinen Wert oder kein Objekt zurück. Das Speichern des zurückgegebenen Wertes (= None) macht also wenig Sinn.
  8. Sie können niemals erwarten, dass die Funktion send () alle übergebenen Daten überträgt. Daher müssen Sie das Ergebnis der Funktion überprüfen und die Situation angemessen behandeln, wenn nicht alle Bytes wirklich übertragen wurden.
  9. Um Threading zu lernen, gibt es sicher bessere Probleme zu lösen als Netzwerkkommunikation, da dieses Thema an sich schon sehr komplex ist.

Neben all diesen Dingen versuche ich hier eine Lösung. Dennoch kann viel verbessert werden. Sie sollten auch die Antwort von Mark Tolonen in Betracht ziehen, da die SocketServer-Klasse sicherlich dazu dient, einige Dinge im Umgang mit dieser Art von Dingen zu erleichtern. Aber du solltest auch weiterhin die Grundlagen lernen.

%Vor%     
Dolphin 01.05.2011, 22:59
quelle
5

Sehen Sie sich die Python-Bibliotheksquelle für SocketServer.py an, insbesondere die Implementierung von server_forever (), um zu sehen, wie ein Server einen Quit implementiert. Es verwendet select (), um den Server-Socket nach neuen Verbindungen abzufragen, und testet ein Beendigungs-Flag. Hier ist ein Hack auf Ihre Quelle, um SocketServer zu verwenden, und ich habe Shout () ein Beendigungs-Flag hinzugefügt. Es wird die Threads Shout und Listen für 5 Sekunden laufen lassen und dann stoppen.

%Vor%     
Mark Tolonen 01.05.2011 16:41
quelle

Tags und Links