基于其他答案中提到的Worker对象方法,我决定查看是否可以扩展解决方案以调用更多线程-在这种情况下,计算机可以运行的最佳数量并以不确定的完成时间启动多个worker。为此,我仍然需要继承QThread的子类-但仅要分配一个线程号并“重新实现”信号“完成”和“开始”以包括其线程号。
我在主GUI,线程和工作程序之间的信号上投入了很多精力。
同样,其他答案也很麻烦地指出,不要将QThread作为父母,但我认为这不是真正的问题。但是,我的代码也要小心销毁QThread对象。
但是,我无法成为工作对象的父对象,因此似乎希望在线程函数完成或GUI被破坏时向它们发送deleteLater()信号。我没有执行此操作就挂起了自己的代码。
我认为有必要进行的另一项改进是重新实现GUI的closeEvent(QWidget),以便指示线程退出,然后GUI会等待所有线程完成。当我玩这个问题的其他答案时,我得到了QThread销毁的错误。
也许对其他人有用。我当然发现它是一个有用的练习。也许其他人会知道线程声明其身份的更好方法。
import sys
from PyQt4.QtCore import QThread, pyqtSlot, pyqtSignal
from PyQt4.QtGui import QApplication, QLabel, QWidget, QGridLayout
import sys
import worker
class Thread(QThread):
startedx = pyqtSignal(int)
finishedx = pyqtSignal(int)
def __init__(self,i,parent=None):
super().__init__(parent)
self.idd = i
self.started.connect(self.starttt)
self.finished.connect(self.finisheddd)
@pyqtSlot()
def starttt(self):
print('started signal from thread emitted')
self.startedx.emit(self.idd)
@pyqtSlot()
def finisheddd(self):
print('finished signal from thread emitted')
self.finishedx.emit(self.idd)
class Form(QWidget):
def __init__(self):
super().__init__()
self.initUI()
self.worker={}
self.threadx={}
self.i=0
i=0
self.threadtest = QThread(self)
self.idealthreadcount = self.threadtest.idealThreadCount()
print("This machine can handle {} threads optimally".format(self.idealthreadcount))
while i <self.idealthreadcount:
self.setupThread(i)
i+=1
i=0
while i<self.idealthreadcount:
self.startThread(i)
i+=1
print("Main Gui running in thread {}.".format(self.thread()))
def setupThread(self,i):
self.worker[i]= worker.Worker(i)
self.threadx[i] = Thread(i,parent=self)
self.threadx[i].setObjectName("python thread{}"+str(i))
self.threadx[i].startedx.connect(self.threadStarted)
self.threadx[i].finishedx.connect(self.threadFinished)
self.worker[i].finished.connect(self.workerFinished)
self.worker[i].intReady.connect(self.workerResultReady)
self.worker[i].finished.connect(self.threadx[i].quit)
self.threadx[i].started.connect(self.worker[i].procCounter)
self.destroyed.connect(self.threadx[i].deleteLater)
self.destroyed.connect(self.worker[i].deleteLater)
self.worker[i].moveToThread(self.threadx[i])
def startThread(self,i):
self.threadx[i].start()
@pyqtSlot(int)
def threadStarted(self,i):
print('Thread {} started'.format(i))
print("Thread priority is {}".format(self.threadx[i].priority()))
@pyqtSlot(int)
def threadFinished(self,i):
print('Thread {} finished'.format(i))
@pyqtSlot(int)
def threadTerminated(self,i):
print("Thread {} terminated".format(i))
@pyqtSlot(int,int)
def workerResultReady(self,j,i):
print('Worker {} result returned'.format(i))
if i ==0:
self.label1.setText("{}".format(j))
if i ==1:
self.label2.setText("{}".format(j))
if i ==2:
self.label3.setText("{}".format(j))
if i ==3:
self.label4.setText("{}".format(j))
@pyqtSlot(int)
def workerFinished(self,i):
print('Worker {} finished'.format(i))
def initUI(self):
self.label1 = QLabel("0")
self.label2= QLabel("0")
self.label3= QLabel("0")
self.label4 = QLabel("0")
grid = QGridLayout(self)
self.setLayout(grid)
grid.addWidget(self.label1,0,0)
grid.addWidget(self.label2,0,1)
grid.addWidget(self.label3,0,2)
grid.addWidget(self.label4,0,3)
self.move(300, 150)
self.setGeometry(0,0,300,300)
self.setWindowTitle('thread test')
self.show()
def closeEvent(self, event):
print('Closing')
i=0
while i <self.idealthreadcount:
self.threadx[i].quit()
i+=1
i=0
while i <self.idealthreadcount:
self.threadx[i].wait()
i+=1
event.accept()
if __name__=='__main__':
app = QApplication(sys.argv)
form = Form()
sys.exit(app.exec_())
还有下面的工作人员代码
import sys
import unittest
from PyQt4.QtCore import QThread, QObject, pyqtSignal, pyqtSlot
import time
import random
class Worker(QObject):
finished = pyqtSignal(int)
intReady = pyqtSignal(int,int)
def __init__(self, i=0):
'''__init__ is called while the worker is still in the Gui thread. Do not put slow or CPU intensive code in the __init__ method'''
super().__init__()
self.idd = i
@pyqtSlot()
def procCounter(self):
for j in range(1, 10):
random_time = random.weibullvariate(1,2)
time.sleep(random_time)
self.intReady.emit(j,self.idd)
print('Worker {0} in thread {1}'.format(self.idd, self.thread().idd))
self.finished.emit(self.idd)
if __name__=='__main__':
unittest.main()
self.finished
信号?例如,如果我不只是打印计数,我想在另一个类的gui的QSpinBox中显示count的值。