2016-04-03 5 views
0

QThreadを '_do_print2'に開始する関数を以下の 'minimal'の例で変更すると、MainWindowがフリーズします。比較のために、上のボタンは問題なくQThreadを開始します。スレッドがMainWindowクラスの子オブジェクトになるのはなぜですか?スレッドがメインスレッドの子オブジェクトでない場合、Qtアプリケーションがフリーズするのはなぜですか?

私はPython 2.7.6とQt 4.8.6を使用しています。

from PyQt4 import QtCore, QtGui 
import sys, time 

class MainWindow(QtGui.QDialog): 
    def __init__(self): 
     super(self.__class__, self).__init__() 
     self.verticalLayout = QtGui.QVBoxLayout(self) 
     self.pushButton = QtGui.QPushButton() 
     self.pushButton2 = QtGui.QPushButton() 
     self.verticalLayout.addWidget(self.pushButton) 
     self.verticalLayout.addWidget(self.pushButton2) 
     QtCore.QObject.connect(self.pushButton, QtCore.SIGNAL('clicked()'), self._do_print) 
     QtCore.QObject.connect(self.pushButton2, QtCore.SIGNAL('clicked()'), self._do_print2) 
    ## Working function 
    def _do_print(self): 
     self.thread = Worker(printer) 
     self.thread.start() 
    ## Function freezes the MainWindow 
    def _do_print2(self): 
     thread = Worker(printer) 
     thread.start() 


def printer(): 
    while True: 
     print "alive" 
     time.sleep(1) 

class Worker(QtCore.QThread): 
    def __init__(self, function, *args, **kwargs): 
     super(self.__class__, self).__init__() 
     self.args = args 
     self.kwargs = kwargs 
     self.function = function 

    def run(self): 
     self.function(*self.args, **self.kwargs) 
     return 

    def __del__(self): 
     self.wait() 

app = QtGui.QApplication(sys.argv) 
window = MainWindow() 
window.show() 
sys.exit(app.exec_()) 

答えて

1

スクリプトは、あなたがそれを正確に行うように言ったので「フリーズ」します。

Workerクラスには、__del__メソッドが定義されています。このメソッドは、runメソッドが返されるまでスレッドを待機させます。しかし、決して終了しないブロッキングループを開始する関数を呼び出すため、もちろん返されることはありません。 __del__メソッドが呼び出されるのは、スレッドへの参照を保持していないため、_do_print2()メソッドが返されるとすぐに(つまり、スレッドが開始された直後に)ガベージコレクションされます。

最初のスレッドはメインウィンドウの子のではありません。これは単にインスタンス属性です(これはそれを生かしています)。 __del__メソッドを削除すると、2番目のスレッドを開始するとおそらくプログラムがクラッシュします。なぜなら、基礎となるC++スレッドが早期に削除されるのを止めるものがないからです。

+0

ガーベッジコレクタは、ワーカースレッドを削除したいと思っています。最初のスレッド( 'window'が実行中)に含まれていますが、削除を待機してスレッドをブロックする必要があります。右? @ JohnH.K。 –

+0

。いいえ、スレッドの即時削除を防ぐ 'wait()'です。私の答えの最後の文を見てください。 – ekhumoro

+0

私は、待たなければならないという関数wait()を意味しました。しかし、この関数はワーカーオブジェクトにあり、メインウィンドウオブジェクトにはありません。メインスレッドは、ワーカーのself .__ del__関数を使用したいと思いますか? –

関連する問題