重用 QRunnable

Re-using QRunnable

我一直在试验 QRunnable 以获取一些服务调用和 运行ning。我从 Qt documentation:

中偶然发现了以下信息

QThreadPool supports executing the same QRunnable more than once by calling tryStart(this) from within QRunnable::run(). If autoDelete is enabled the QRunnable will be deleted when the last thread exits the run function. Calling start() multiple times with the same QRunnable when autoDelete is enabled creates a race condition and is not recommended.

有人能解释一下这是什么意思吗?我写了下面的代码,它允许我连续多次执行一个 QRunnable 对象:

#!/usr/bin/env python

from PyQt4.QtCore import QRunnable, pyqtSlot, pyqtSignal, QObject, QThread, QThreadPool
from PyQt4.QtGui import QApplication, QWidget, QPushButton, QHBoxLayout, QLabel
from sys import exit, argv
from random import getrandbits

class ServiceCallSignals(QObject):
  srv_status = pyqtSignal(bool)
  srv_running = pyqtSignal(bool)

class ServiceCall(QRunnable):

  def __init__(self):
    super(ServiceCall, self).__init__()
    self.signals = ServiceCallSignals()

  def run(self):
    self.signals.srv_running.emit(True)
    call = bool(getrandbits(1))
    print('QRunnable Thread ID: %d' % int(QThread.currentThreadId()))
    if call: QThread.sleep(5)

    self.signals.srv_status.emit(call)
    self.signals.srv_running.emit(False)

class Test(QWidget):

  def __init__(self):
    super(Test, self).__init__()
    self.initUI()

  def initUI(self):

    layout = QHBoxLayout(self)

    self.cb = QPushButton('Send request', self)
    self.cb.clicked.connect(self.srv_send)
    layout.addWidget(self.cb)

    self.lbl = QLabel('Waiting...', self)
    layout.addWidget(self.lbl)

    self.srv = ServiceCall()
    self.srv.setAutoDelete(False)
    self.srv.signals.srv_status.connect(self.srv_receive)
    self.srv.signals.srv_running.connect(self.srv_block)
    self.tp = QThreadPool(self)

    self.setGeometry(300, 300, 250, 150)
    self.setWindowTitle('QRunnable and ROS service calls')
    self.show()

  @pyqtSlot()
  def srv_send(self):
    print('Main Thread ID: %d' % int(QThread.currentThreadId()))
    self.tp.start(self.srv)
    self.cb.setText('Running for reply')

  @pyqtSlot(bool)
  def srv_block(self, state):
    self.cb.setEnabled(not state)

  @pyqtSlot(bool)
  def srv_receive(self, srv_res):
    if srv_res: self.lbl.setText('Success')
    else: self.lbl.setText('Failed')
    self.cb.setText('Send request')

def main():

  app = QApplication(argv)
  t = Test()
  exit(app.exec_())


if __name__ == '__main__':
  main()

文档中的引述是否意味着我做错了? 如果我把我的 QThreadPooltryStart(self) 放在我的 运行 我收到很多很多线程 运行ning...

文档说 支持run() 中调用 tryStart,而不是 必需 .

如果您在 run() 之外顺序调用 start(),它将重新使用同一个线程。但是,如果您在 run() 内调用 tryStart(),它可能会在必要时保留额外的线程。

您需要 .setAutoDelete(0) 才能使用 trystart()Autodelete(0)表示线程执行后不会自动删除,需要手动删除。

然后在使用 trystart() 而不是 start() 启动/重新启动线程时,避免了竞争条件,因为同一个线程继续运行。 它在文档中。 祝你好运