带有 QThread 和线程模块的 Python 多线程

Posted

技术标签:

【中文标题】带有 QThread 和线程模块的 Python 多线程【英文标题】:Python Multithreading with QThread and Threading Modules 【发布时间】:2017-04-12 07:06:33 【问题描述】:

我尝试在程序中启动一个 Qthread 和另一个线程。代码如下所示。 Qthread 必须显示图形。 Qthread 单独运行时工作正常,但当我尝试使用一个线程或多个 Qthread 运行时,它不显示任何内容。

我的设置:ubuntu 16.04.1 LTS,python 2.7.12

模块:pyqtgraph、时间、numpy、sys、线程

QThread:plotthread.py

from pyqtgraph.Qt import QtGui, QtCore
import pyqtgraph as pg
import numpy as np
import time
import sys
class guiThread(QtCore.QThread):
    def __init__(self):
        QtCore.QThread.__init__(self)
        self.status=True
        self.range=100
        self.app = QtGui.QApplication(sys.argv)
        self.app.aboutToQuit.connect(self.stop)
        self.win = pg.GraphicsWindow(title="Example")
        self.win.resize(500,400)
        pg.setConfigOptions(antialias=True)
        self.px = self.win.addPlot(title="X plot")
        self.ckx = self.px.plot(pen='y')
        self.cdx = self.px.plot(pen='r')
        self.px.setXRange(0, self.range)
        self.px.setYRange(-180, 180)
        self.px.showGrid(x=True, y=True)
        self.timer = QtCore.QTimer()
        self.timer.timeout.connect(self.updateplot)
        self.timer.start(0.001)
        self.kx=np.zeros(self.range)
        self.dx=np.zeros(self.range)

    def updateplot(self):
        self.ckx.setData(self.kx)
        self.cdx.setData(self.dx)

    def append(self,sin):
        self.kx=np.roll(self.kx,-1)
        self.kx[-1]=sin[0]
        self.dx=np.roll(self.dx,-1)
        self.dx[-1]=int(sin[1])
    def stop(self):
        print "Exit" #exit when window closed
        self.status=False
        sys.exit()
    def run(self):
        print "run" #Qthread run
        while self.status:
            sin=np.random.randint(-180,180,2) 
            self.append(sin) #append random number for plot
            time.sleep(0.01)

Python 线程:ptiming.py

import  time
import threading

class timeThread (threading.Thread):
    def __init__(self,name):
        threading.Thread.__init__(self)
        self.name=name
        self.t=time.time()
        self.elapsed=0
    def run(self):
        print "thread start"
        while (1):
            self.elapsed=time.time()-self.t
            print self.name, self.elapsed

主要:ma​​in.py

import ptiming
import plotthread
t1=plotthread.guiThread()
t1.start()
t2=ptiming.timeThread("t1")
t2.start()

【问题讨论】:

您是否尝试在 guiThread 构造函数中添加 win.show() 您不能在单独的线程中执行任何类型的 gui 操作。所有 gui 操作必须发生在主线程中。 @mguijarr 是的,我在 plotthread 的 init 和 run 函数中做了 @ekhumoro:你是对的,但在这种情况下,UI 元素是在主线程中创建的(就像在类构造函数中完成的那样)并且更新由计时器处理 - 所以应该是在线程安全方面还可以 @mguijarr。确实如此,但考虑到代码当前的结构,尚不清楚其意图是什么。 OP 还说:“QThread 必须显示图形”。所以很难理解 OP 真正想要实现的目标。 【参考方案1】:

在您的timeThread 类中,.run() 方法执行一个繁忙的循环:它连续显示经过的时间,没有任何暂停,因此 CPU 变得疯狂,我猜操作系统没有调度其他线程。

在此循环中执行某种time.sleep() - 应该会恢复正常。

旁注:为什么要在 guiThread 类构造函数中创建 UI 元素?使用 Qt,在任何情况下,所有 UI 元素都属于主线程。正如@ekhumoro 所说,GUI 操作必须发生在主线程中,您的代码就是这种情况,尽管它的编写方式令人困惑。就我个人而言,我会明确 UI 元素是在主线程中创建的,并且我会添加一个数据处理线程。

【讨论】:

以上是关于带有 QThread 和线程模块的 Python 多线程的主要内容,如果未能解决你的问题,请参考以下文章

PyQt5中多线程模块QThread解决界面卡顿无响应问题,线程池ThreadPoolExecutor解决多任务耗时操作问题

PyQt5中多线程模块QThread解决界面卡顿无响应问题,线程池ThreadPoolExecutor解决多任务耗时操作问题

PyQt5中多线程模块QThread解决界面卡顿无响应问题,线程池ThreadPoolExecutor解决多任务耗时操作问题

[ PyQt入门教程 ] PyQt5中多线程模块QThread使用方法

QThread:使用 GUI python 进行线程化

QThread如何从其自己的线程发送一个带有枚举作为QML消耗参数的信号?