简体   繁体   中英

explanation needed for this subclassing QThread vs moveToThread example

I am trying to create a new thread worker outside of my GUI. When I subclass QThread it works as I expect, the GUI is unaffected. When I use the moveToThread technique, I get full lock up of the GUI. I assume I'm accidentally putting the new thread into the main thread, but I don't understand what I'm doing to cause that. How can have the start2 function work without freezing the main thread?

from PySide import QtGui, QtCore
import sys
import time

class THREAD(QtCore.QThread):
    def __init__(self):
        super(THREAD, self).__init__()

    def run(self):
        time.sleep(5)
        print "done"

class WORKER(QtCore.QObject):
    def __init__(self):
        super(WORKER, self).__init__()

    def run(self):
        time.sleep(5)
        print "done"

class GUI(QtGui.QDialog):
    def __init__(self):
        super(GUI, self).__init__()

        mainLayout = QtGui.QHBoxLayout()
        self.setLayout(mainLayout)
        start1Button = QtGui.QPushButton("Start1")
        start2Button = QtGui.QPushButton("Start2")
        mainLayout.addWidget(start1Button)
        mainLayout.addWidget(start2Button)
        start1Button.clicked.connect(self.start1)
        start2Button.clicked.connect(self.start2)

    def start1(self):
        self.myThread = THREAD()
        self.myThread.start()

    def start2(self):
        myWorker = WORKER()
        myThread = QtCore.QThread()
        myThread.start()
        myWorker.moveToThread(myThread)
        myWorker.run()

def main():
    app = QtGui.QApplication(sys.argv)
    ex = GUI()
    ex.show()
    sys.exit(app.exec_())

if __name__ == '__main__':
    main()

Firstly, you need to keep a reference the worker and thread you have created, otherwise they will get garbage-collected as soon as start2() returns.

Secondly, calling myWorker.run() directly inside start2() means it will be executed within the main thread. So you must arrange to have it called later, after the thread has started. The usual way to do this is by using a signal.

Your code should therefore look something like this:

    def start2(self):
        self.myWorker = WORKER()
        self.myThread2 = QtCore.QThread()
        self.myWorker.moveToThread(self.myThread2)
        self.myThread2.started.connect(self.myWorker.run)
        self.myThread2.start()

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM