2

2つのスレッドを持つアプリがあります。1つは単純なゲームを実行するpygameスレッドで、もう1つはゲームの制御に使用されるメッセージを受け入れるリスニングサーバーです。

簡略化された擬似コードは次のとおりです。

class ServerThread(threading.Thread):
    def run(self):
        class SingleTCPHandler(SocketServer.BaseRequestHandler):
            try:
                while(1):
                ...
                #Receive messages from socket. Add them to pygame event queue
                ...
            except KeyboardInterrupt:
                sys.exit(0)
...
...
class PygameThread(threading.Thread):
    def run(self):
    ...
    #pygame stuff
    ...
    #The following pygame code closed the app when closing the pygame window while running as a single thread
        for event in pygame.event.get():
                if event.type==QUIT:
                    exit()
   ...
try:
    server_thread = ServerThread()
    server_thread.start()
    pygame_thread = PygameThread()
    pygame_thread.start()
except KeyboardInterrupt:
    sys.exit(0)

例外はいずれもキャッチされていないようです。私はpygameスレッドと:なしでサーバーだけを実行しようとしました:

        try:
            while(1):
            ...
            #Receive messages from socket. Add them to pygame event queue
            ...
        except KeyboardInterrupt:
            sys.exit(0)

に応答しませんCtrl + c

pygameウィンドウの標準の閉じるボタン(小さなx op right)は機能しなくなりました。

そして、回避策の私の試み:

try:
    server_thread = ServerThread()
    server_thread.start()
    pygame_thread = PygameThread()
    pygame_thread.start()
except KeyboardInterrupt:
    sys.exit(0)

また、動作していません。

アプリを起動したシェルを強制終了せずにアプリを閉じるためのアイデアを探しています。

更新しました

提案に基づいて、私は次のことを行いました。while True両方のトレッドの前者をに変更しましたwhile not self.stop_requested:

そしてまた:

try:
    pygame_thread = PygameThread()
    pygame_thread.start()
    server_thread = ServerThread()
    server_thread.start()
except KeyboardInterrupt:
    pygame_thread.stop_requested = True
    server_thread.stop_requested = True

それはまだ機能していません。また、Ctrl + cで終了しようとすると、このコードを実行するコンソールで、出力されるだけであることに気付きました。

alan@alan ~/.../py $ python main.py 
^C^C^C^C^C^C^C

更新しました

少しショートカットを作成し、サーバースレッドをデーモンに変更したので、pygameウィンドウ(pygameスレッド)が閉じられると閉じます。

4

2 に答える 2

1

メインプログラムのexceptブロックで、どういうわけか自分Threadで停止するように通知する必要があります。このスレッドで私の答えを見て、私が何を意味するのかを理解することができます。

基本的に、while(1):-loopを-loopに置き換えwhile not self.stop_requested:ます。KeyboardInterrupt次に、が実際にキャッチされるメインスレッド内からクラスのこのフィールドを設定できます。次にjoin()、メインスレッドの各スレッドも実行する必要があります。そうすれば、すべてが停止したことが安全にわかります。

ところで:私はまったく使用while(1)しません。1はループwhile Trueの各反復として評価されるため、より直感的です。期待されるところにbool書いてみませんか?bool括弧も冗長です。この種の表記法は、ブール型を持たない古き良きCにまでさかのぼります。

于 2013-01-11T09:30:13.447 に答える
1

sys.exit実際には何も終了または「終了」しないため、やや紛らわしい名前です。例外をスローするだけで、スレッドでそれを行うと、例外はそのスレッドに対してローカルのままになります。SystemExitメインコンテキストをスローするには、が必要になりますthread.interrupt_main

于 2013-01-11T08:50:09.573 に答える