问题
I have an app with two threads. One is a pygame thread which runs a simple game, the other thread is a listening server which accepts messages which are used to control the game.
Here is the stripped down pseudo code:
class ServerThread(threading.Thread):
def run(self):
class SingleTCPHandler(SocketServer.BaseRequestHandler):
try:
while(1):
...
#Receive messages from socket. Add them to pygame event queue
...
except KeyboardInterrupt:
sys.exit(0)
...
...
class PygameThread(threading.Thread):
def run(self):
...
#pygame stuff
...
#The following pygame code closed the app when closing the pygame window while running as a single thread
for event in pygame.event.get():
if event.type==QUIT:
exit()
...
try:
server_thread = ServerThread()
server_thread.start()
pygame_thread = PygameThread()
pygame_thread.start()
except KeyboardInterrupt:
sys.exit(0)
It seems that none of the exceptions are being caught. I've tried running just the server without the pygame thread and the:
try:
while(1):
...
#Receive messages from socket. Add them to pygame event queue
...
except KeyboardInterrupt:
sys.exit(0)
doesn't respond to Ctrl + c
The pygame window standard close button (the little x op right) doesn't work anymore.
And my try of a workaround:
try:
server_thread = ServerThread()
server_thread.start()
pygame_thread = PygameThread()
pygame_thread.start()
except KeyboardInterrupt:
sys.exit(0)
also isn't working.
I'm looking for ideas to close the app without having to kill the shell from which the app has been started.
Updated
Based on the suggestion i did the following:
Changed the former while True
in both treads to while not self.stop_requested:
.
And also:
try:
pygame_thread = PygameThread()
pygame_thread.start()
server_thread = ServerThread()
server_thread.start()
except KeyboardInterrupt:
pygame_thread.stop_requested = True
server_thread.stop_requested = True
It still isn't working. I also noticed that in the console which runs this code when I try to terminate with Ctrl+c, it only gets printed out.
alan@alan ~/.../py $ python main.py
^C^C^C^C^C^C^C
Updated
I did a little shortcut and changed the server thread to daemon, so it closes once the pygame window (which is tha pygame thread) is closed.
回答1:
In the except
-block of your main program, you should somehow notify your Thread
s to stop on their own. You can look at my answer in this thread to get an idea of what I mean.
Basically, substitute the while(1):
-loop by a while not self.stop_requested:
-loop. You can then set this field of your class from inside your main thread, where the KeyboardInterrupt
is actually caught. Then you should also join()
each thread from your main thread, and then you safely know everthing stopped.
BTW: I would not use while(1)
at all. while True
is more intuitive, as the 1 is evaluated as a bool
each iteration of the loop. Why not write a bool
where it is expected? The parentheses are redundant as well. This kind of notation goes back to good-old C, which doesn't have a boolean-type.
回答2:
sys.exit
is somewhat confusing name, since it doesn't actually terminate or "exit" anything. It only throws an exception, and if you do that in a thread, the exception remains local to that thread. To throw SystemExit
in the main context you're going to need thread.interrupt_main.
来源:https://stackoverflow.com/questions/14274327/close-multi-threaded-application-with-keyboardinterrupt