0

情况是这样的:

我正在使用 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

(记住很多不是真正的代码或函数——这只是让你知道我认为什么是一个很好的解决方案)

4

1 回答 1

0

请查看作为 Pythonthreading库的一部分的守护线程。线程默认是非守护进程的,如果只有守护线程在运行,Python 会让你退出。如果您在第一次创建后台游戏逻辑线程时将其指定为守护线程,则当您的主非守护线程退出时,该线程将自动被杀死。

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

于 2013-09-01T07:53:38.323 回答