状況は次のとおりです。
WXWidgets を使用して簡単なゲームを作成しています。私が持っているロジックは、ゲームのメイン ルーチンが最初に GUI を起動し、次にゲームのロジックを実際に実行するために新しい別のスレッドを生成するというものです。ゲーム ロジックは順次実行され、ときどき (ただしそれほど頻繁ではありません)、GUI を介してユーザーからの入力を受け取り、ゲーム データで GUI を更新します。ゲームは多くのオーディオを使用するため、GUI 自体はあまり操作されていません。
ゲーム スレッドは、ブロックしなければならない処理を行うことがよくあります。これは、ゲームであることを考えると適切です。AI の計算、インターネットからのデータの読み込みなどはすべて、ゲーム スレッドのブロックを引き起こします。ゲーム スレッドが 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
(その多くは実際のコードや関数ではないことを覚えておいてください。これは、私が考えていたことが良い解決策になると考えているだけです)