Python 2: Best way to terminate WXWidgets app main thread when user closes
app?
The situation is this:
I'm writing a simple game using WXWidgets. The logic I have is that the
game's main routine first launches the GUI, and then spawns a new separate
thread to actually run the game's logic. The game logic runs sequentially,
occasionally (but not very frequently) accepting input from the user via
the GUI and updating the GUI with game data. The game uses a lot of audio
so the GUI itself is not being manipulated much.
The game thread often does things that must block - and this is
appropriate given that this is a game. AI computations, loading data from
the Internet, etc. all cause the game thread to block. This is fine since
the game thread manages the UI to make sure users can't manipulate the UI
in any situation where the game thread might not be able to respond.
The problem arises if the user hits Alt+F4 or Command-Q to exit the app
completely. This causes the main GUI to close, but it obviously does not
kill the game logic thread. The game thread continues running in the
background, now disconnected from the UI, and as soon as it tries to
interact with the UI it will crash (as would be expected in that
situation).
What I am looking to do is to have a way to signal to the thread that the
user has exited the app - BUT - without having to litter my code with tons
of "check if the user closed the GUI" routines. First of all, that method
wouldn't even always work since, as I said, often the game thread blocks
while it is doing something and thus several seconds could go by where
such a call never gets checked.
Since the game thread starts out as a function, I was thinking a good way
to possibly solve this would be if there is some way for me to cause a
custom exception to be raised on the thread. I could then write a simple
wrapper function would wrap the main game function inside a try block,
specifically looking for that exception. If that exception is raised, I
could then gracefully close sockets, shut down AI players, etc. as
necessary, then gracefully exit the thread.
Is there a way to cause something like this to happen?
Here is some very rough pseudocode to illustrate the problem:
Currently:
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
Very ugly method:
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!!!
What I'd like to be able to do:
def PlayGame(self):
try:
self._PlayGame()
except UserExitedApplicationError:
self.AI.Stop()
self.sockets.closeAll()
return # return gracefully so thread exits
(Remember a lot of that is not real code or functions - this just gives
you the idea of what I was thinking would be a good solution)
No comments:
Post a Comment