Python 2:用户关闭应用程序时终止WXWidgets应用程序主线程的最佳方法?

时间:2013-09-01 07:44:17

标签: python multithreading

情况如下:

我正在使用WXWidgets编写一个简单的游戏。我的逻辑是游戏的主程序首先启动GUI,然后产生一个新的独立线程来实际运行游戏的逻辑。游戏逻辑顺序地,偶尔地(但不是非常频繁地)通过GUI接受来自用户的输入并用游戏数据更新GUI。游戏使用大量音频,因此GUI本身不会受到太多操作。

游戏线程经常做必须阻止的事情 - 这是适当的,因为这是一个游戏。 AI计算,从Internet加载数据等都会导致游戏线程被阻塞。这很好,因为游戏线程管理UI以确保用户无法在游戏线程可能无法响应的任何情况下操纵UI。

如果用户点击Alt + F4或Command-Q完全退出应用程序,则会出现问题。这会导致主GUI关闭,但它显然不会杀死游戏逻辑线程。游戏线程继续在后台运行,现在与UI断开连接,一旦它尝试与UI交互,它就会崩溃(正如在那种情况下预期的那样)。

我要做的是有一种方法向线程发出用户退出应用程序的信号 - 但是 - 不必乱丢我的代码,大量的“检查用户是否关闭了GUI”例程。首先,这个方法甚至不会一直有效,因为正如我所说的那样,游戏线程经常会在它做某事时阻塞,因此几秒钟就可以通过这样的调用永远不会被检查。

由于游戏线程是作为一个函数启动的,我想一个可能解决这个问题的好方法是,如果有一些方法让我在线程上引发自定义异常。然后我可以编写一个简单的包装函数将主游戏函数包装在try块中,特别是查找该异常。如果引发异常,我可以根据需要优雅地关闭套接字,关闭AI玩家等,然后优雅地退出线程。

有没有办法让这样的事情发生?

这是一个非常粗略的伪代码来说明问题:

目前:

def PlayGame(self):
    # Get the game ready
    self.initGame()

    # Go into a loop to run the game
    while (True):
        # Get user's move
        move = self.GUI_GetMove()
        # Act based on the move
        gameOver = self.processMove(move)
        # If we got True, game is over.
        if (gameOver == True): return
        # Run the AI's logic - THIS MIGHT BLOCK AS THE AI PROCESSES AND/OR 
        # GRABS STUFF OFF THE INTERNET ETC.
        move = self.AI_GetMove()
        # Act based on the move
        gameOver = self.processMove(move)
        # (Let's pretend in this game the AI never ends the game)
        continue

非常难看的方法:

def PlayGame(self):
    # Get the game ready
    self.initGame()

    # Go into a loop to run the game
    while (True):
        # Get user's move
        move = self.GUI_GetMove()
        if (move == "EXIT" or self.GUI_Exited == True):
            return
        # Act based on the move
        gameOver = self.processMove(move)
        # If we got True, game is over.
        if (gameOver == True): return
        if (self.GUI_Exited == True):
            return
        # Run the AI's logic - THIS MIGHT BLOCK AS THE AI PROCESSES AND/OR 
        # GRABS STUFF OFF THE INTERNET ETC.
        move = self.AI_GetMove()
        # self.AI_GetMove might take 10 or more seconds - game will appear to
        # be STUCK if user exits during an AI Process!
        if (self.GUI_Exited == True):
            return
        # Act based on the move
        gameOver = self.processMove(move)
        if (self.GUI_Exited == True):
            return
        # (Let's pretend in this game the AI never ends the game)
        continue

        # That self.GUI_Exited code is duplicated SO many times - making
        # this an awfully ugly and confusing block of code! In the real
        # app, the check might need to be duplicated 100+ times!!!

我希望能够做到:

def PlayGame(self):
    try:
        self._PlayGame()
    except UserExitedApplicationError:
        self.AI.Stop() 
        self.sockets.closeAll() 
        return # return gracefully so thread exits

(记住很多不是真正的代码或功能 - 这只是让你知道我在想什么是一个很好的解决方案)

1 个答案:

答案 0 :(得分:0)

请查看守护程序线程作为Python threading库的一部分。默认情况下,线程是非守护进程,如果只有守护程序线程正在运行,Python将允许您退出。如果您在第一次创建后台游戏逻辑线程时将其指定为守护程序线程,则当您的主非守护程序线程退出时,该线程将自动被终止。

请注意,这只是最简单,最直接的方法,它有其缺点。线程将在释放任何资源之前被杀死。您还可以使用线程信令使该线程在停止之前首先释放其资源。最简单的线程信令形式是事件,也是threading库的一部分。