2

GUIといくつかのワーカースレッドを使用してアプリケーションを構築しています。マルチスレッドアプリケーションにしたいので、同じスレッドをループで数回実行します。各スレッドは、スレッド外のクラスで定義された異なる入力パラメーターを取得します。

したがって、私のmainGui.pyファイルは次のようになります(関連するコードのみが表示されています)。

self.workers = [worker.Worker(), worker.Worker(), worker.Worker()]
for i in xrange(threadCount):
    self.currentWorker = self.workers[i]
    self.currentWorker.alterTable.connect(self.alterMainTable)
    self.currentWorker.start()
    time.sleep(0.1)

ご想像のとおり、私はワーカーのalterTable信号をalterMainTable()メインのGUIスレッドで定義したメソッドに接続しています。このメソッドは、GUIのテーブルを更新します。

ワーカースレッドは次のようになります。

class Worker(QThread):

    alterTable = Signal(dict)

    def __init__(self, parent=None):
        super(Worker, self).__init__(parent)

    def sendToTable(self, param1, param2, param3):
        """This method emits the signal with params as defined above"""
        params = {}
        params["param1"] = param1
        params["param2"] = param2
        params["param3"] = param3
        self.alterTable.emit(params)

    def run(self):
        #Perform a lengthy task, do this every now and then:
        self.sendToTable(param, param2, param3)

このアプリケーションを単一のワーカースレッドで実行している場合(つまり、メインスレッドでそのループを呼び出していない場合)、正常に動作します。シグナルが発行され、GUIのメインテーブルが更新されます。

ただし、一度に複数のスレッドを実行すると問題が発生します。ワーカースレッドはその役割を果たしますが、シグナルはたまにしか発行されません。または、さらに良いことに、Qt(またはその他)がすべてのスレッドの終了を待っているかのように出力され、テーブルを更新します。これは文字通り何が起こるかです-Pythonコンソールで、スレッドがタスクを実行していることがわかります。すべてのスレッドが実行していることを実行すると、テーブルに突然大量のデータが一度に入力されます。

ご想像のとおり、これから生じるもう1つの問題は、処理中のイベントがないため、しばらくするとアプリケーションがフリーズしたように見えることです。

Qt.DirectConnectionメソッドにを追加しようとしましたconnect()が、それは実際には役に立ちませんでした。

ボーナスの質問:私はSOや他のウェブサイトでこのトピックについて読んでいますがQRunnable()QThread()特にサブクラス化する場合は、人々が推奨するのではないようです。したがって、私はを使用しQThreadPool()ます。しかし、これを試したところ、-から信号を発することができないようです-SignalがQRunnableクラス内で定義されていても、QRunnable-それは私に信号を与えます-これはかなり奇妙です、私は言わなければなりません。AttributeError: 'PySide.QtCore.Signal' object has no attribute 'connect'

編集:SOに関する別の回答で、誰かが、処理されるイベントでメインGUIスレッドを「スパム」している可能性があると述べました。sendToTable()ただし、 QThreadのメソッドはスレッドから最大で5〜6回しか呼び出されず、threadCount最大で20を超えることはないため、これが当てはまるとは思いませんが、通常は5前後に保ちます。 。

4

1 に答える 1

2

そして、いつものように、デバッグの2日後、SOに投稿してから数分後に質問に答えます。

workerThread.wait()すべてのスレッドが開始された後、残りのメソッド呼び出しがありました。したがって、当然、私のアプリケーションは、指示されたとおりに実行しました。スレッドが終了するのを待ちました。

そのメソッド呼び出しを削除しQCoreApplication.processEvents()、スレッドを開始したループの内側にも配置しました。これで、すべてが魅力のように機能します。

もう一度、SOの目に見えない全能の人に感謝します!

于 2012-11-29T05:06:26.730 に答える