使用KeyboardInterrupt关闭多线程应用程序 [英] Close multi threaded application with KeyboardInterrupt

查看:784
本文介绍了使用KeyboardInterrupt关闭多线程应用程序的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个有两个线程的应用程序。一个是一个运行简单游戏的pygame线程,另一个线程是一个监听服务器,接受用于控制游戏的消息。



这是一个被删除的伪代码:

  class ServerThread(threading.Thread):
def run(self):
class SingleTCPHandler (SocketServer.BaseRequestHandler):
try:
while(1):
...
#从套接字接收消息。将它们添加到pygame事件队列
...
除了KeyboardInterrupt:
sys.exit(0)
...
...
class PygameThread (threading.Thread):
def run(self):
...
#pygame stuff
...
#以下pygame代码关闭了应用程序在pygame.event.get()中为事件运行时关闭pygame窗口

如果event.type == QUIT:
exit()
..
try:
server_thread = ServerThread()
server_thread.start()
pygame_thread = PygameThread()
pygame_thread.start()
除了KeyboardInterrupt:
sys.exit(0)

似乎没有任何异常被捕获。我试过运行只是服务器没有pygame线程和:

  try:
while(1):
...
#从套接字接收消息。将它们添加到pygame事件队列
...
除了KeyboardInterrupt:
sys.exit(0)

不响应 Ctrl + c



pygame窗口标准关闭按钮(小x对右)不再工作。



我尝试解决方法:

  try:
server_thread = ServerThread()
server_thread.start()
pygame_thread = PygameThread()
pygame_thread.start()
除了KeyboardInterrupt:
sys.exit(0)

也不工作。



我正在寻找想法来关闭应用程序,而不必杀死应用程序启动的shell。



更新



根据我的建议,我做了以下操作:
更改了以前的 中,而不是self.stop_requested:

lso:

  try:
pygame_thread = PygameThread()
pygame_thread.start()
server_thread = ServerThread()
server_thread.start()
除了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

已更新



我做了一个小快捷方式,将服务器线程更改为守护程序,所以一旦pygame窗口(这是pygame线程)被关闭,它就关闭。

解决方案

您的主程序的 -block,您应该以某种方式通知您的线程来自行停止。您可以在此线程以了解我的意思。



基本上,替换 while(1):循环一个而不是self.stop_requested: -loop。然后,您可以从主线程内部设置该类的该字段,其中 KeyboardInterrupt 实际被捕获。那么你也应该从你主线程中的每个线程的 join(),然后安全地知道一切都停止。



BTW:我根本不会使用 while(1)而True 更直观,因为1被评估为循环的每次迭代的 bool 。为什么不写一个 bool 预期的地方?括号也是多余的。这种符号可以追溯到古老的C,它没有布尔类型。


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.

解决方案

In the except-block of your main program, you should somehow notify your Threads 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.

这篇关于使用KeyboardInterrupt关闭多线程应用程序的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆