2

スレッドを作成しようとしていますが、wxPython アプリのフレームが閉じられたときに終了します。これが私のコードです:

#! /usr/bin/env python

import time, wx
from threading import Thread

class UpdateThread(Thread):
    def __init__(self):
        self.stopped = False
        Thread.__init__(self)
    def run(self):
        while not self.stopped:
            self.updateExchange()
            time.sleep(1)
    def updateExchange(self):
        print("Updated...")

class tradeWindow(wx.Frame):
    def __init__(self, parent, id):
        wx.Frame.__init__(self, parent, id, "Exchange", size = (500, 190))
        panel = wx.Panel(self)
    def OnExit(self):
        tickThread.stopped # I've also tried: tickThread.stopped = True

tickThread = UpdateThread()
tickThread.start()
if __name__ == "__main__":
    app = wx.PySimpleApp()
    frame = tradeWindow(parent = None, id = -1)
    frame.Show()
    app.MainLoop()

しかし、フレームを閉じると、印刷が続けられます。

4

2 に答える 2

6

魔法のFrame.OnExit方法はありません。フレームとアプリを混同しています。フレームは、他のウィンドウと同様に閉じます。アプリが終了します。

OnExitしたがって、アプリ クラスのメソッドにコードを入れることができます。しかし、それはあなたがここで望むものではありません。

メソッドについては、この簡単なチュートリアルをご覧くださいOnExit。繰り返しますが、ここで必要なことではありませんが、それがどのように機能するか (およびどのオブジェクトで呼び出されるか) を知っておく必要があります。

ウィンドウで必要なものはいつでもバインドEVT_CLOSEして呼び出すことができます。ただし、これを明示的に行う必要があります。

通常、メソッドOnCloseまたはを呼び出しますOnCloseWindow。それを呼び出すことOnExitは、大きな混乱につながるだけです(そうです)。

バインド先のイベント ハンドラー メソッドは、実際にはイベント ハンドラーである必要があります。つまり、eventパラメーター (およびself) を取ります。

次に、EVT_CLOSEハンドラーを追加すると、デフォルトのハンドラーが上書きされます。つまり、Destroy自分で実行しない限り呼び出されません。

これはbinding に関するチュートリアルEVT_CLOSEで、上記のすべてのステップを示しています。

最後に、DavidRobinson が説明したように、実行するだけでは何も起こりtickThread.stoppedません。に設定する必要がありますTrue

すべてを一緒に入れて:

class tradeWindow(wx.Frame):
    def __init__(self, parent, id):
        wx.Frame.__init__(self, parent, id, "Exchange", size = (500, 190))
        panel = wx.Panel(self)
        self.Bind(wx.EVT_CLOSE, self.OnClose)
    def OnClose(self, event):
        tickThread.stopped = True
        self.Destroy()

もう 1 つ注意:

深刻なスレッド化されたプログラムでは、スレッド間で値を共有したい場合、通常、何らかの同期オブジェクトと同期する必要があります。別のスレッドからのシグナルを待っている場合、それを処理する一般的な方法はCondition. 一方、値を共有したいだけの場合は、Lock.

自分が何をしているのかを本当に理解している場合は、Global Interpreter Lock に同期を処理させて問題を解決できることがよくあります。しかし、一般的に、これは悪い考えです。たとえば、メイン スレッドがコア 0 で実行され、バックグラウンド スレッドがコア 1 で実行されている場合、Python 言語定義には、コンピューターが更新された値をコア 0 のキャッシュからコア 1 にコピーすることを保証するものは何もありません。そのため、バックグラウンド スレッドが永久に回転し、古い値を監視し、新しい値を確認することはできません。結局のところ、x86 上の CPython 2.0-3.3 では、これがコードで発生する可能性はありません。


最後に、デーモン スレッドが適切なソリューションかどうかを尋ねました。ドキュメントから:

このフラグの意味は、デーモン スレッドだけが残ったときに Python プログラム全体が終了することです。

つまり、プログラムはデーモン スレッドを停止することなく終了できます。しかし…</p>

注 デーモン スレッドは、シャットダウン時に突然停止します。それらのリソース (開いているファイル、データベース トランザクションなど) が適切に解放されない可能性があります。スレッドを正常に停止させたい場合は、スレッドを非デーモン化し、Event.

于 2013-03-13T04:21:50.897 に答える
1

tickThread.setDaemon(True)前に設定してみてくださいtickThread.start()-デーモンスレッドは親スレッドで終了する必要があります。

于 2013-03-13T04:16:39.580 に答える