重用 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()
文档中的引述是否意味着我做错了? 如果我把我的 QThreadPool
和 tryStart(self)
放在我的 运行 我收到很多很多线程 运行ning...
文档说 支持 在 run()
中调用 tryStart
,而不是 必需 .
如果您在 run()
之外顺序调用 start()
,它将重新使用同一个线程。但是,如果您在 run()
内调用 tryStart()
,它可能会在必要时保留额外的线程。
您需要 .setAutoDelete(0)
才能使用 trystart()
。
Autodelete(0)
表示线程执行后不会自动删除,需要手动删除。
然后在使用 trystart()
而不是 start()
启动/重新启动线程时,避免了竞争条件,因为同一个线程继续运行。
它在文档中。
祝你好运
我一直在试验 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()
文档中的引述是否意味着我做错了? 如果我把我的 QThreadPool
和 tryStart(self)
放在我的 运行 我收到很多很多线程 运行ning...
文档说 支持 在 run()
中调用 tryStart
,而不是 必需 .
如果您在 run()
之外顺序调用 start()
,它将重新使用同一个线程。但是,如果您在 run()
内调用 tryStart()
,它可能会在必要时保留额外的线程。
您需要 .setAutoDelete(0)
才能使用 trystart()
。
Autodelete(0)
表示线程执行后不会自动删除,需要手动删除。
然后在使用 trystart()
而不是 start()
启动/重新启动线程时,避免了竞争条件,因为同一个线程继续运行。
它在文档中。
祝你好运