使用键盘Interrup关闭多线程应用程序

2024-10-01 13:29:23 发布

您现在位置:Python中文网/ 问答频道 /正文

我有一个有两个线程的应用程序。一个是运行一个简单游戏的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线程和:

^{pr2}$

不响应Ctrl + c

pygame窗口的标准关闭按钮(右上方的小x)不再工作。在

我尝试了一种变通方法:

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线程)关闭,它就会关闭。在


Tags: 服务器event应用程序serverexit线程threadpygame
2条回答

sys.exit是一个令人困惑的名称,因为它实际上并不终止或“退出”任何内容。它只抛出一个异常,如果你在一个线程中这样做,这个异常仍然是该线程的本地异常。要在主上下文中抛出SystemExit,您需要^{}。在

在主程序的except-块中,您应该以某种方式通知您的Thread自行停止。你可以看看我在this thread里的答案,了解我的意思。在

基本上,将while(1):-循环替换为while not self.stop_requested:-循环。然后,您可以从主线程内部设置类的这个字段,在这里KeyboardInterrupt实际上被捕捉到。然后,您还应该join()从主线程开始的每个线程,然后您就可以安全地知道所有的线程都停止了。在

顺便说一句:我根本不会用while(1)while True更直观,因为1在循环的每次迭代中都被计算为bool。为什么不在预期的地方写一个bool?括号也是多余的。这种表示法可以追溯到旧的C语言,它没有布尔类型。在

相关问题 更多 >