我有一个有两个线程的应用程序。一个是pygame线程,它运行一个简单的游戏,另一个线程是一个监听服务器,它接受用于控制游戏的消息。
下面是剥离后的伪代码:
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)
似乎没有捕获任何异常。我试过只运行服务器没有pygame线程和:
try:
while(1):
...
#Receive messages from socket. Add them to pygame event queue
...
except KeyboardInterrupt:
sys.exit(0)
对Ctrl + c
无反应
pygame窗口标准关闭按钮(小x op右)不再工作。
和我尝试的变通方法:
try:
server_thread = ServerThread()
server_thread.start()
pygame_thread = PygameThread()
pygame_thread.start()
except KeyboardInterrupt:
sys.exit(0)
也不能工作。
我正在寻找关闭应用程序而不必杀死应用程序已启动的外壳的想法。
根据这个建议,我做了以下的事情: 将两个踏面的前
while True
改为while not self.stop_requested:
。也:
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
它仍然不工作。我还注意到,在运行这段代码的控制台中,当我尝试用Ctrl+c终止时,它只被打印出来。
alan@alan ~/.../py $ python main.py
^C^C^C^C^C^C^C
我做了一个小快捷方式,并将服务器线程更改为daemon,因此一旦pygame窗口(即pygame线程)关闭,它就会关闭。
在主程序的except
块中,您应该以某种方式通知Thread
s自行停止。你可以看看我在这个帖子里的回答,了解我的意思。
基本上,用while not self.stop_requested:
循环代替while(1):
循环。然后,您可以在主线程内部设置类的这个字段,在这里实际捕获KeyboardInterrupt
。然后你还应该从主线程中join()
每个线程,然后你就知道一切都停止了。
顺便说一句:我不会使用while(1)
。while True
更直观,因为每次循环迭代时,1都被计算为bool
。为什么不在预期的地方写一个bool
呢?括号也是多余的。这种符号可以追溯到古老的C语言,它没有布尔类型。
sys.exit
是一个有点令人困惑的名字,因为它实际上并没有终止或"退出"任何东西。它只抛出一个异常,如果在一个线程中这样做,异常仍然是该线程的局部异常。要在主上下文中抛出SystemExit
,您将需要thread.interrupt_main
。