QObject或继承QThread是否更好地执行和监视外部进程?

时间:2016-01-21 11:01:02

标签: qt pyqt qthread qprocess qobject

我已经将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类属性不会导致此类问题。

0 个答案:

没有答案