中断 QThread 睡眠 [英] Interrupting QThread sleep
问题描述
我想知道如何暂停 QThread,然后在收到信号时恢复.我已经阅读并知道我可以做这样的事情:
I would like to know how to pause a QThread and then resume when I get a signal. I have read and know that I can do something like this:
def run(self):
...
self.ready=False
while not self.ready:
self.sleep(1)
...
...
@QtCore.Slot()
def set_ready(self):
self.ready = True
然而,我想做的是避免线程中的轮询.我不想将睡眠时间设置为很短的时间并继续检查.我想睡觉,直到我的主线程收到信号以继续.
However, what I want to do is avoid the polling in the thread. I don't want to have to set the sleep to a short amount of time and keep checking. I want to go to sleep until I get a signal from my main thread to continue.
我在我的线程中所做的是:
What I am doing in my thread is this:
(pseudo code)
with open file:
read a block of data
while data:
sendThread = send the block via UDP
read the next block of data
while not ready or sendThread.isRunning:
sleep(0.1)
在我的主线程中,我设置了一个 QtNetwork.QUdpSocket
来将 readyRead 连接到一个方法来处理传入的数据报并对其进行解码.当它得到我正在等待的响应时,它会向 set_ready
槽发送一个信号,告诉线程发送另一个数据报.我并不总是知道另一个系统需要多长时间才能响应,尽管我可能会有一些 30 秒左右的长时间超时值.
In my main thread I have setup a QtNetwork.QUdpSocket
to connect readyRead to a method to handle incoming datagrams and decode them. When it gets the response that I'm waiting for it sends a signal to the set_ready
slot to tell the thread to send another datagram. I don't always know how long it will take for the other system to respond, though I will likely have some long timeout value of 30seconds or so.
有没有办法中断线程的睡眠?所以我可以做这样的事情:
Is there a way to interrupt the sleep of the thread? so I could do something like this:
sleep(30)
if not ready:
Timeout occurred stop processing
else:
Continue processing.
推荐答案
您可以使用 QThreads
的 worker 模式 轻松完成此操作.QThread
文档中有一个 example.确切的代码会有所不同,具体取决于您使用的是 PyQt
还是 PySide
(看起来您使用的是 PySide
示例).
You can do this pretty easily using the worker pattern of using QThreads
. There's an example in the QThread
documentation. The exact code will be a little different depending on whether you're using PyQt
or PySide
(it looks like you're using PySide
from your example).
与 PyQt
相比,PySide
的一个显着问题是 他们没有包装QtCore.Q_ARG
,所以在PyQt
中,你通常可以使用QMetaObject.invokeMethod
从主线程调用 Worker
对象上的插槽(带参数),你不能直接在 PySide
中这样做,必须创建一个 dummy 信号(即 Main.send_signal
)连接到工作线程上的插槽,以便您可以从主线程调用它.
One notable issue with PySide
compared to PyQt
is that they didn't wrap QtCore.Q_ARG
, so in PyQt
, where you could normally use QMetaObject.invokeMethod
to call a slot (with arguments) on the Worker
object from the main thread, you can't do that directly in PySide
and have to create a dummy signal (ie. Main.send_signal
) to connect to the slot on the worker so you can call it from the main thread.
import time
import sys
from PySide import QtCore, QtGui
class Worker(QtCore.QObject):
send_signal = QtCore.Signal(str) # using PySide
# QtCore.pyqtSignal(str) ## using PyQt
# @QtCore.pyqtSlot(str)
@QtCore.Slot(str)
def receive_slot(self, data):
# data could be a filepath
# open file
# ... do stuff
# close file
QtCore.QThread.sleep(1) # to simulate doing stuff
self.send_signal.emit(data + ' success')
class Main(QtGui.QWidget):
send_signal = QtCore.Signal(str)
def __init__(self):
super(Main, self).__init__()
self.worker = Worker()
self.thread = QtCore.QThread(self)
self.worker.moveToThread(self.thread)
self.worker.send_signal.connect(self.receive_slot)
self.send_signal.connect(self.worker.receive_slot)
self.thread.start()
self.send_signal.emit('Start')
@QtCore.Slot(str)
def receive_slot(self, data):
print 'Main: {}'.format(data)
self.send_signal.emit('Message {}'.format(time.time()))
if __name__ == '__main__':
app = QtGui.QApplication(sys.argv)
window = Main()
window.show()
app.exec_()
这篇关于中断 QThread 睡眠的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!