如何解决如何推迟 QRunnable 的执行,直到发出来自前一个的信号
为了不冻结 PyQT GUI,我使用 QRunnable(在后台执行的函数)和 QThreadPool。我有三个函数,其中一个需要前两个函数的结果才能运行,我正在努力确保在前两个函数返回各自的结果后开始执行第三个函数。
QThreadPool 的类定义如下:
class Worker(QtCore.QRunnable):
'''
Worker thread
Inherits from QRunnable to handler worker thread setup,signals and wrap-up.
:param callback: The function callback to run on this worker thread. Supplied args and
kwargs will be passed through to the runner.
:type callback: function
:param args: Arguments to pass to the callback function
:param kwargs: Keywords to pass to the callback function
'''
def __init__(self,fn,*args,**kwargs):
super(Worker,self).__init__()
# Store constructor arguments (re-used for processing)
self.running = None
self.fn = fn
self.args = args
self.kwargs = kwargs
self.signals = WorkerSignals()
# Add the callback to our kwargs
self.kwargs['callback_progress'] = self.signals.progress
self.kwargs['callback_data'] = self.signals.data
# @Slot()
def run(self):
'''
Initialise the runner function with passed args,kwargs.
'''
# Retrieve args/kwargs here; and fire processing using them
try:
self.signals.started.emit()
self.result = self.fn(
*self.args,**self.kwargs
)
except:
traceback.print_exc()
exctype,value = sys.exc_info()[:2]
self.signals.error.emit((exctype,value,traceback.format_exc()))
else:
self.signals.result.emit(self.result) # Return the result of the processing
finally:
self.signals.finished.emit() # Done
和信号
class WorkerSignals(QtCore.QObject):
'''
Defines the signals available from a running worker thread.
Supported signals are:
finished
No data
error
`tuple` (exctype,traceback.format_exc() )
result
`object` data returned from processing,anything
progress
`int` indicating % progress
'''
error = QtCore.Signal(tuple)
started = QtCore.Signal()
finished = QtCore.Signal()
progress = QtCore.Signal(int)
result = QtCore.Signal(object)
data = QtCore.Signal(dict)
def exe_worker_run(self,WorkerPool,function,arguments):
Worker = thread.Worker(function,arguments)
Worker.signals.started.connect(self.sig_thread_start)
Worker.signals.error.connect(self.sig_thread_error)
Worker.signals.result.connect(self.sig_thread_result)
Worker.signals.finished.connect(self.sig_thread_finish)
WorkerPool.start(Worker)
发出结果的信号连接到函数
def sig_thread_result(self,result):
for key in result.keys():
try:
dfrm = getattr(self,key)
print('{} {} loaded!!!'.format(time.time(),key))
except:
pass
主要问题是每个函数的结果都是在所有函数执行完后才发出的。所以我需要的是允许保持 QRunnable 的执行直到前一个 QRunnable 的结果可用的解决方案。
解决方法
您可以将任务组织到队列中并通过信号槽机制将它们一一传递给工作人员执行。通过这种方式,您可以使用一次计算的结果来安排下一次计算。
from PySide2 import QtCore,QtWidgets,QtGui
class Task:
def __init__(self,taskId):
self._taskId = taskId
def taskId(self):
return self._taskId
def execute():
pass
class TaskPlusOne(Task):
def __init__(self,taskId,value):
super().__init__(taskId)
self._value = value
def execute(self):
QtCore.QThread.currentThread().sleep(3)
return self._value + 1
class Worker(QtCore.QObject):
complete = QtCore.Signal(int,object)
def append(self,task):
print("execute",task.taskId())
res = task.execute()
self.complete.emit(task.taskId(),res)
class Window(QtWidgets.QWidget):
task = QtCore.Signal(object)
def __init__(self,parent = None):
super().__init__(parent)
worker = Worker()
self.task.connect(worker.append)
worker.complete.connect(self.onComplete)
thread = QtCore.QThread()
worker.moveToThread(thread)
thread.start()
self._thread = thread
self._worker = worker
self._queue = [TaskPlusOne(0,0)]
self.executeOne()
def executeOne(self):
queue = self._queue
if len(queue) == 0:
print("task queue is empty")
return
self.task.emit(queue.pop(0))
def executeAll(self):
while len(self._queue) > 0:
self.executeOne()
def onComplete(self,res):
print("onComplete",taskId)
if res < 2:
print("append task to queue")
self._queue.append(TaskPlusOne(taskId + 1,res))
self.executeOne()
def closeEvent(self,event):
thread = self._thread
thread.quit()
thread.wait()
super().closeEvent(event)
if __name__ == "__main__":
app = QtWidgets.QApplication([])
widget = Window()
widget.show()
app.exec_()
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。