在QThreadPool中行为不端的QSignals,在python中使用QThead的QRnnable

时间:2014-11-15 09:52:09

标签: python multithreading qt qthread

我陷入了一种情况,即我的前几个信号通过,后来没有信号被发射。

我会详细说明:

我的工作需要繁重的处理和ram,并且可能需要2-4个小时来完成它而不需要线性方式的线程,所以我决定使用QTheadPool,所以我创建(测试时)355个QRunner通过QThreadPool。其中很少(QRunners)依赖于另一个QRunners来完成。它一切正常,我能够通过发出信号并捕获它们来获得依赖关系。当我在没有GUI的情况下运行它时,它的工作绝对完美

例如(下面的代码没有经过测试,我只是在这里输入):

from PyQt4 import QtCore

class StreamPool(QtCore.QObject):
  def __init__(self, inputs, q_app):
    super(....)

    self.inputs = inputs
    self.q_app = q_app

    self.pool = QtCore.QThreadPool()

  def start(self):
    for each_input in self.inputs:
      runner = StreamRunner(each_input, self.q_app)
      runner.signal.operation_started.connect(self.mark_as_start)
      runner.signal.operation_finished.connect(self.mark_as_start)
      self.pool.start(runner)

  def mark_as_start(self, name):
    print 'operation started..', name
    # Some operation...

  def mark_as_finish(self, name):
    print 'operation finished..', name
    # Some operation...

class StreamRunner(QtCore.QRunnable):
  def __init__(self, input, q_app):
    super(..)

    self.input = input            
    self.q_app = q_app
    self.signal = WorkSignals()


  def run(self):
    self.signal.operation_started.emit(input)
    self.q_ap

    # Doing some operations

    self.signal.operation_finished.emit(input)
    self.q_app.processEvents()    

class WorkSignals(QtCore.QObject):
  operation_started = QtCore.pyqtSignal(str)
  operation_finished= QtCore.pyqtSignal(str)



if __name__ == '__main__':
  app = QtGui.QApplication([])      
  st = StreamPool(['a', 'b', 'c'], app)
  st.start()
  app.exec_()

在上述情况下它的效果非常好。

我想在ui中显示状态,因为可以执行数百个任务,所以我编写了一个简单的ui,并从另一个QThread运行StreamPool()让我们说命名为 - StreamWorkThread(),它是由生成的ui和StreamWorkThread捕获StreamPool.signal。*并将它们发送回ui,但在这种情况下,StreamPool只能发出少数几个,即起始4或5,尽管任务仍在执行但依赖任务未初始化由于这种行为,并没有在ui中显示状态更新。

我无法与你们分享代码,因为它来自我的工作场所,我可以在这里写出类似的方法

class StreamWorkThread (QtCore.QThread):
  def __init__(self, inputs, q_app):
    super(..)

    self.signal = WorkSignals()
    self.stream_pool = StreamPool(inputs, q_app)self.stream_pool.signal.operation_started.connect(self.signal.operation_started.emit)
    self.stream_pool.signal.operation_finished.connect(self.signal.operation_finished.emit)

  def run(self):
    self.stream_pool.start()


def print_start(name):
  print 'Started --', name

def print_finished(name):
  print 'Finished --', name

if __name__ == '__main__':
  app = QtGui.QApplication([])      
  th = StreamWorkThread (['a', 'b', 'c'], app)
  th.signal.operation_started.connect(print_start)
  th.signal.operation_finshed.connect(print_finished)
  th.start()
  app.exec_()

合并代码:

from PyQt4 import QtCore

class StreamPool(QtCore.QObject):
  def __inti__(self, inputs, q_app):
    super(StreamPool, self).__init()

    self.inputs = inputs
    self.q_app = q_app

    self.pool = QtCore.QThreadPool()

  def start(self):
    for each_input in self.inputs:
      runner = StreamRunner(each_input, self.q_app)
      runner.signal.operation_started.connect(self.mark_as_start)
      runner.signal.operation_finished.connect(self.mark_as_start)
      self.pool.start(runner)

  def mark_as_start(self, name):
    print 'operation started..', name
    # Some operation...

  def mark_as_finish(self, name):
    print 'operation finished..', name
    # Some operation...

class StreamRunner(QtCore.QRunnable):
  def __init__(self, input, q_app):
    super(StreamRunner, self).__init()

    self.input = input            
    self.q_app = q_app
    self.signal = WorkSignals()


  def run(self):
    self.signal.operation_started.emit(input)
    self.q_ap

    # Doing some operations

    self.signal.operation_finished.emit(input)
    self.q_app.processEvents()    

class WorkSignals(QtCore.QObject):
  operation_started = QtCore.pyqtSignal(str)
  operation_finished= QtCore.pyqtSignal(str)

class StreamWorkThread (QtCore.QThread):
  def __init__(self, inputs, q_app):
    super(StreamWorkThread, self).__init()

    self.signal = WorkSignals()
    self.stream_pool = StreamPool(inputs,q_app)
    self.stream_pool.signal.operation_started.connect(self.signal.operation_started.emit)
    self.stream_pool.signal.operation_finished.connect(self.signal.operation_finished.emit)

  def run(self):
    self.stream_pool.start()


def print_start(name):
  print 'Started --', name

def print_finished(name):
  print 'Finished --', name

if __name__ == '__main__':
  app = QtGui.QApplication([])      
  th = StreamWorkThread (['a', 'b', 'c'], app)
  th.signal.operation_started.connect(print_start)
  th.signal.operation_finshed.connect(print_finished)
  th.start()
  app.exec_()

请大家帮助我,我不知道这里到底是什么问题..! :(

2 个答案:

答案 0 :(得分:0)

没有源代码就很困难,但问题可能出在" app.exec _()"运行后,gui的主循环启动并干扰您的Streamx类

答案 1 :(得分:0)

好的,我得到了这种行为的解决方案。

阻止信号的根本原因是在StrealPool中继承QObject,当我用QThread替换QObject时,它无缝地工作。

以下是我所做的更改,只有两个地方

class StreamPool(**QtCore.QThread**):
  def __inti__(self, inputs, q_app):
    super(StreamPool, self).__init()

    self.inputs = inputs
    self.q_app = q_app

    self.pool = QtCore.QThreadPool()

  def **run**(self):
    for each_input in self.inputs:
      runner = StreamRunner(each_input, self.q_app)
      runner.signal.operation_started.connect(self.mark_as_start)
      runner.signal.operation_finished.connect(self.mark_as_start)
      self.pool.start(runner)

那套,它有效! :d