情况是这样的:
我正在使用 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
(记住很多不是真正的代码或函数——这只是让你知道我认为什么是一个很好的解决方案)