2017-10-01 1 views
1

Ich implementiere Multithreading in PyQt5 und Python 3.5 durch Ausführen einer Worker innerhalb einer QThread. Im folgenden Beispiel wird thread2_worker (läuft in einem sekundären Thread und) erstellt thread3_worker, verbindet thread3_worker.finished Signal an thread3_worker_finished() und führt es.PyQt - Signal für Objekt erstellt in anderen Thread funktioniert nicht

Wenn thread3_worker fertig ist, sendet es finished aus seinem Thread, aber die Verbindung funktioniert nicht. Meine Vermutung ist, dass es damit zu tun hat, dass thread3_worker nicht im Hauptthread erstellt oder verbunden wird, aber ich würde jede Klärung begrüßen.

import time 
from PyQt5.QtCore import QObject, QThread, pyqtSignal, pyqtSlot, QCoreApplication 


class Worker(QObject): 
    # Generic worker. 
    finished = pyqtSignal() 

    def __init__(self, func): 
     super().__init__() 
     self.func = func 

    def run(self): 
     self.func() 
     self.finished.emit() 


def thread_factory(func): 
    # Creates a Worker, a QThread and moves the Worker inside the QThread. 
    worker = Worker(func) 
    thread = QThread() 
    worker.moveToThread(thread) 
    thread.started.connect(worker.run) 

    # Provision graceful termination. 
    worker.finished.connect(thread.quit) 
    worker.finished.connect(worker.deleteLater) 
    thread.finished.connect(thread.deleteLater) 

    return worker, thread 


def wait(): 
    print("thread3:\t{}".format(QThread.currentThread())) 
    time.sleep(3) 


# finished signal of thread3_worker is never received. 
@pyqtSlot() 
def thread3_worker_finished(): 
    QCoreApplication.exit() 


def create_thread3(): 
    print("thread2:\t{}".format(QThread.currentThread())) 
    global thread3_worker, thread3 
    # thread3_worker runs inside thread3, and all it does is call wait(). 
    thread3_worker, thread3 = thread_factory(wait) 
    thread3_worker.finished.connect(thread3_worker_finished) # FIXME Doesn't work. 
    thread3.start() 


app = QCoreApplication([]) 
print("Main thread:\t{}".format(QThread.currentThread())) 
thread3_worker, thread3 = None, None 
# thread2_worker runs inside thread2, and creates and runs thread3_worker. 
thread2_worker, thread2 = thread_factory(create_thread3) 
thread2.start() 
app.exec_() 

Antwort

0

Cross-Thread-Signale erfordern eine Event-Schleife. Ihre thread_factory Funktion verbindet das finished Signal des Arbeiters mit dem quit Steckplatz seines Threads. Der Slot quit fordert den Thread auf, seine Ereignisschleife zu verlassen.

Nach dem Start von thread3 wird worker2 beendet und thread2 beendet. Wenn dann das finished-Signal von worker3 ausgegeben wird, wird keine Ereignisschleife mehr ausgeführt, die es verarbeiten kann. Wenn Sie die Zeile worker.finished.connect(thread.quit) auskommentieren, sollte Ihr Beispiel funktionieren.

+0

In der Tat, das Auskommentieren von 'worker.finished.connect (thread.quit)' hat es behoben. Vielen Dank für Ihr Wissen. Ich dachte, dass jeder QThread eine eigene Event-Schleife hat. – R01k

+1

@ R01k. Jeder Thread hat eine eigene Event-Schleife. Aber worker3 benötigt die Ereignisschleife von thread2 (weil das Signal über Threads ausgesendet wird). – ekhumoro

+0

Da die Thread-Event-Schleife weiterläuft, nachdem ihr Worker fertig ist, löscht 'thread.deleteLater()' den Thread letztendlich noch? – R01k

Verwandte Themen