2012-05-11 15 views
0

私はGUI用にwxPythonを使用しています。 AppLogicクラスでは、この非常にクラスのメソッドで実行されるワーカースレッドがあります。ここでこのデッドロックを理解していますか?

class GUI: 
    _wx_app = None 
    _main_window = None 
    _app_logic = None 

    def start(self): 
     # bla bla bla 
     self._main_window.Show() 
     self._app_logic.begin() 
     self._wx_app.MainLoop() 

    def _cancel_listener(self): 
     """Called from MainWindow, if the user has clicked the cancel 
     button.""" 
     print("I'm leaving this scope.") 
     self._app_logic.cancel() # Should cancel the task done in 
            # a second thread. 

    def _status_listener(self, status_text): 
     """Called often by the worker thread.""" 
     print("Here I am again.") 
     if self._main_window.status.GetLabel() != status_text: 
      self._main_window.status.SetLabel(status_text) 

上から_cancel_listenerによって呼び出されAppLogicクラスからメソッドを取り消しています:

この

GUIクラスで何とか

def cancel(self): 
     self._shall_abort = True 
     self._thread.join(self._some_time_out) 
     assert self._thread.isAlive() == False 

joinGetLabel(とデッドロックがありますしたがって、MainLoop?)が関与していますが、実際に何が起こっているのか分かりません。誰かがこれについてより多くの洞察を持っていますか?それは素晴らしいだろう!

+0

'どういうわけか、参加するとデッドロックがあります' - ではない巨大な驚き、TBH :(参加()最高のGUIアプリケーションでは回避された非GUIアプリケーションでは、参加する()最高の回避さ –

答えて

2

すべてのGUIツールキットは、メインGUIのスレッドを持っています。それらはすべて、スレッドセーフな方法でGUIウィジェットを操作できる特別なメソッドを持っています。 wxPythonの世界では、それらのメソッドはwx.CallAfter、wx.CallLater、wx.PostEventです。私はあなたの例のどこにそれらが表示されないので、あなたがやっていることは基本的にGUIのスレッドを一時停止したり、何かが "未定義"になることです。

ここ

は、スレッドとwxPythonの記事のカップルです:

+0

あなたの答えをありがとう。要約:私は 'join'でGUIスレッドをブロックしています。ワーカースレッドは' GUI'クラスが登録したリスナーを呼び出します。 +++どうしてなぜワーカースレッドの呼び出しスタックに 'GetLabel'やそれ以降の呼び出しが含まれていないのですか?ブロックするGUIフレームワーク内にスレッド同期ポイントがありますか? – rynd

+1

私は本当に分かりませんが、wxのメインスレッドを直接呼び出す場合は、問題が発生します。だから、私はあなたがスレッドセーフメソッドを使用する必要がある、またはあなたの他のスレッドが完了するまでメインループを更新しないと言った理由です。 –

2

私はここに私のフィールドの外だけど、私はwxPythonの答えを待って、その後、GUIスレッドを経由して子ウィンドウにメッセージを送信することにより、他のツールキットのような働きを疑います。この場合、GetLabel()またはSetLabel()メソッドはメインメッセージループ(== GUIスレッド)を通過し、応答が入るまで呼び出しスレッドを停止する必要があります。

キャンセル)GUIスレッドから、それはアボート変数を設定し、その後self._thread.join()で終了する他のスレッドを待機するので、他のスレッドが停止するまで、それ以上のメッセージが処理されていません。しかし、他のスレッドはGetLabel()メッセージ - >ビンゴへの応答を待っています!

+0

私は今だけGUI' 'の範囲を検討している+++私はあなたの説明この方法を理解して:。。。' GetLabel'はdoesnのGUIスレッドがキャンセル時にハングアップするために戻ってこない。スタックを深くするだけですか? +++これは、このトピックについての私の心に入ってくるものです: 'MainLoop'が既にあるため、このスタック部の停止する:' MainWindow'> '_cancel_listener'>' cancel'で 'MainLoop'>何か。したがって、 'GetLabel'は' MainLoop'が直前の呼び出しチェーンを処理するまで待つだけです。しかし、それは起こりません。 +++この試行された説明は正しいですか? +++非常に複雑です!私の脳は揚げられている。 – rynd

関連する問題