Wie zu verwenden QThread richtig in pyqt mit moveToThread()?
habe ich diesen Artikel gelesen Wie Wirklich, Wirklich Verwenden QThreads; Die Vollständige Erklärung, heißt es statt Unterklasse qthread, und implementieren Sie die run () -, sollte man Sie nutzen moveToThread zu schieben ein QObject auf QThread Beispiel mit moveToThread(QThread*)
hier ist der c++ - Beispiel, aber ich weiß nicht, wie es zu konvertieren, um python-code.
class Worker : public QObject
{
Q_OBJECT
QThread workerThread;
public slots:
void doWork(const QString ¶meter) {
//...
emit resultReady(result);
}
signals:
void resultReady(const QString &result);
};
class Controller : public QObject
{
Q_OBJECT
QThread workerThread;
public:
Controller() {
Worker *worker = new Worker;
worker->moveToThread(&workerThread);
connect(workerThread, SIGNAL(finished()), worker, SLOT(deleteLater()));
connect(this, SIGNAL(operate(QString)), worker, SLOT(doWork(QString)));
connect(worker, SIGNAL(resultReady(QString)), this, SLOT(handleResults(QString)));
workerThread.start();
}
~Controller() {
workerThread.quit();
workerThread.wait();
}
public slots:
void handleResults(const QString &);
signals:
void operate(const QString &);
};
QThread* thread = new QThread;
Worker* worker = new Worker();
worker->moveToThread(thread);
connect(worker, SIGNAL(error(QString)), this, SLOT(errorString(QString)));
connect(thread, SIGNAL(started()), worker, SLOT(process()));
connect(worker, SIGNAL(finished()), thread, SLOT(quit()));
connect(worker, SIGNAL(finished()), worker, SLOT(deleteLater()));
connect(thread, SIGNAL(finished()), thread, SLOT(deleteLater()));
thread->start();
ich habe mit dieser Methode zum generieren einer qthread , aber wie Sie sehen können, es ist mit dem nicht empfohlenen Weg. wie kann ich wieder schreiben, dass die bevorzugte Methode ?
class GenericThread(QThread):
def __init__(self, function, *args, **kwargs):
QThread.__init__(self)
# super(GenericThread, self).__init__()
self.function = function
self.args = args
self.kwargs = kwargs
def __del__(self):
self.wait()
def run(self, *args):
self.function(*self.args, **self.kwargs)
Bearbeiten: zwei Jahre später ...
Ich habe versucht, qris' code funktioniert es und im anderen thread
import sys
import time
from PyQt4 import QtCore, QtGui
from PyQt4.QtCore import pyqtSignal, pyqtSlot
import threading
def logthread(caller):
print('%-25s: %s, %s,' % (caller, threading.current_thread().name,
threading.current_thread().ident))
class MyApp(QtGui.QWidget):
def __init__(self, parent=None):
QtGui.QWidget.__init__(self, parent)
self.setGeometry(300, 300, 280, 600)
self.setWindowTitle('using threads')
self.layout = QtGui.QVBoxLayout(self)
self.testButton = QtGui.QPushButton("QThread")
self.testButton.released.connect(self.test)
self.listwidget = QtGui.QListWidget(self)
self.layout.addWidget(self.testButton)
self.layout.addWidget(self.listwidget)
self.threadPool = []
logthread('mainwin.__init__')
def add(self, text):
""" Add item to list widget """
logthread('mainwin.add')
self.listwidget.addItem(text)
self.listwidget.sortItems()
def addBatch(self, text="test", iters=6, delay=0.3):
""" Add several items to list widget """
logthread('mainwin.addBatch')
for i in range(iters):
time.sleep(delay) # artificial time delay
self.add(text+" "+str(i))
def test(self):
my_thread = QtCore.QThread()
my_thread.start()
# This causes my_worker.run() to eventually execute in my_thread:
my_worker = GenericWorker(self.addBatch)
my_worker.moveToThread(my_thread)
my_worker.start.emit("hello")
# my_worker.finished.connect(self.xxx)
self.threadPool.append(my_thread)
self.my_worker = my_worker
class GenericWorker(QtCore.QObject):
start = pyqtSignal(str)
finished = pyqtSignal()
def __init__(self, function, *args, **kwargs):
super(GenericWorker, self).__init__()
logthread('GenericWorker.__init__')
self.function = function
self.args = args
self.kwargs = kwargs
self.start.connect(self.run)
@pyqtSlot()
def run(self, *args, **kwargs):
logthread('GenericWorker.run')
self.function(*self.args, **self.kwargs)
self.finished.emit()
# run
app = QtGui.QApplication(sys.argv)
test = MyApp()
test.show()
app.exec_()
den, Ausgang:
mainwin.__init__ : MainThread, 140221684574016,
GenericWorker.__init__ : MainThread, 140221684574016,
GenericWorker.run : Dummy-1, 140221265458944,
mainwin.addBatch : Dummy-1, 140221265458944,
mainwin.add : Dummy-1, 140221265458944,
mainwin.add : Dummy-1, 140221265458944,
mainwin.add : Dummy-1, 140221265458944,
mainwin.add : Dummy-1, 140221265458944,
mainwin.add : Dummy-1, 140221265458944,
mainwin.add : Dummy-1, 140221265458944,
moveToThread(thread)
ist die bevorzugte Art und Weise, aber doch alle Beispiel-code habe ich in der Lage zu finden, Unterklassen QThread.run()
und setzen dort arbeiten. Es wäre toll, wenn wir sehen könnten, ein Beispiel oder ein Muster verwenden.Hier ist ein Artikel, der hat mir sehr geholfen bei der Umsetzung mein Erster thread: mayaposch.wordpress.com/2011/11/01/... . Als Sie sagte, dass es nicht eine empfohlene Praxis, um eine Unterklasse QThread auch wenn es eine Menge von tutorials zu tun.
Ist das Letzte Beispiel in der Frage richtig? mainwin.hinzuzufügen ist, wo der code fügt das Element an das listwidget, aber deutlich von der gedruckten Ausgabe können wir sehen, tat mainwin.add ausgeführt in den thread?!?
InformationsquelleAutor Shuman | 2013-12-02
Du musst angemeldet sein, um einen Kommentar abzugeben.
Den Standard run () - Implementierung in QThread betreibt eine event-Schleife, die für Sie das äquivalent von:
Wichtige Sache über eine Ereignis-Schleife, die es ermöglicht, Objekte im Besitz von der thread zum empfangen von Ereignissen auf Ihre slots, die ausgeführt werden, in diesem thread. Diese Objekte sind nur QObjects, nicht QThreads.
Wichtiger Hinweis: der QThread-Objekt ist nicht im Besitz eigener thread! Es wurde auf dem Haupt-thread und lebt dort. Abgesehen von seiner run-Methode, die alle Ihre code ausführt, in den Haupt-thread.
So dass Sie sollten in der Lage sein, dies zu tun:
Auch, denken Sie sorgfältig über das, was passiert mit dem Ergebnis
self.function
, die derzeit verworfen. Könnten Sie erklären, ein weiteres signal aufGenericWorker
, empfängt das Ergebnis und haben dierun()
Methode emittieren, die signalisieren, wenn es fertig ist, übergeben das Ergebnis an.http://ilearnstuff.blogspot.co.uk/2012/09/qthread-best-practices-when-qthread.html
Wichtiger Hinweis: stellen Sie sicher, dass
my_thread
undmy_worker
gespeichert werden, wenn Sie Sie erstellen, die in einer Methode, da sonst der garbage collector Papierkorb, und der Arbeiter wird nicht ausgeführtInformationsquelleAutor qris
War ich versucht, qris Beispiel in meine Anwendung ein, hielt sich aber mit meinem code ausführen, in der mein Haupt-thread! Es ist der Weg der signal , erklärte er Anruf ausführen!
Grundsätzlich, wenn Sie es anschließen in den Konstruktor des Objekts wird die Verbindung existiert zwischen zwei Objekten in der main-thread - weil die QObject - Eigenschaften gehören zu den Threads, die Sie erstellt. Beim verschieben der QObject zu deinem neuen thread, die Verbindung nicht mit Ihnen bewegen. Nehmen Sie die Zeile, die verbindet das signal an die run-Funktion, und schließen Sie es , nachdem du die Arbeiter seines neuen thread!
Den relevanten Veränderung von qris Antwort:
InformationsquelleAutor Matthew Runchey