中断 QThread 睡眠 [英] Interrupting QThread sleep

查看:70
本文介绍了中断 QThread 睡眠的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想知道如何暂停 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.

推荐答案

您可以使用 QThreadsworker 模式 轻松完成此操作.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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆