我已经将QThread
子类化了,并添加了一些功能,例如启动用户定义的外部流程,监控其行为(是否已启动?,是否已停止,退出代码是什么等)以及报告通过插槽和信号返回主线程(即根据进程状态更新UI)。然而,我遇到了一个问题:
QObject: Cannot create children for a parent that is in a different thread.
(Parent is QProcess(0x2baa7a0), parent's thread is QThread(0x28150a0), current thread is WorkerForExtProcess(0x2b77680)
这是我的代码:
class WorkerForExtProcess(QtCore.QThread):
'''
A worker thread used by each ThreadedWidget to do some specified amount of work
'''
EXT_PROC_STATUS_INACTIVE = 0
EXT_PROC_STATUS_OK_RUNNING = 1
EXT_PROC_STATUS_OK_FINISHED = 2
EXT_PROC_STATUS_ERROR_FAIL_START = 3
EXT_PROC_STATUS_ERROR_FAIL_QUIT = 4
def __init__(self, ext_process_name):
print('WorkerForExtProcess in thread %d' % QtCore.QThread.currentThreadId())
QtCore.QThread.__init__(self)
self.ext_process_name = ext_process_name
self.ext_process = QtCore.QProcess()
self.signalFinishedExtProc = QtCore.SIGNAL('ext_proc_finished')
self.signalProgressExtProc = QtCore.SIGNAL('ext_proc_progress')
# self.emit(self.signalFinishedExtProc, self.EXT_PROC_STATUS_INACTIVE)
def run(self):
self.ext_process.start(self.ext_process_name)
if self.ext_process.waitForStarted():
print('External process "%s" was started successfully (PID: %d)' % (self.ext_process_name, self.ext_process.pid()))
self.emit(self.signalFinishedExtProc, self.EXT_PROC_STATUS_OK_RUNNING)
else:
print('Failed to start external process "%s"' % self.ext_process_name)
self.emit(self.signalFinishedExtProc, self.EXT_PROC_STATUS_ERROR_FAIL_START)
return
if self.ext_process.waitForFinished() and not self.ext_process.exitCode():
self.emit(self.signalFinishedExtProc, self.EXT_PROC_STATUS_OK_FINISHED)
else:
print('Failed to quit external process "%s" properly' % self.ext_process_name)
self.emit(self.signalFinishedExtProc, self.EXT_PROC_STATUS_ERROR_FAIL_QUIT)
print('External process log:\n\tExit code: %dExit status: %d\n' % (self.ext_process.exitStatus(), self.ext_process.exitCode()))
问题是QThread
的实例归主线程和self.ext_process
所有。 run()
本身就是在一个单独的线程中实际运行的。
现在,如果我创建ext_process
变量并将其初始化为run()
方法中包含的偶数循环
def run(self):
ext_process = QtCore.QProcess()
ext_process.start(self.ext_process_name)
...
问题已解决,因为QProcess
实例的线程关联性是INSIDE我的子类所代表的附加线程。
然而,这有一个重大缺陷 - 如果我要添加一些与ext_process
一起使用的插槽和信号(例如发送一些POSIX信号),除了类属性之外它不能是其他任何东西,以便我可以访问它从各处。如果我这样做,我会回到原来的地方 - cannot create children for a parent that ...
。
如果我切换到QObject
会解决此问题吗?据我所知,在使用QOBJECT.moveToThread(QTHREAD)
时,这基本上会改变该QObject
实例的整个线程关联性,并且从那一刻起它不再存在于其先前的线程中,而是存在于新的线程中,从而使我的变量ext_process
类属性不会导致此类问题。