PyQt5动态运行同一线程

2024-09-28 01:26:59 发布

您现在位置:Python中文网/ 问答频道 /正文

我正在使用python 3.7和pyqt5

我想做的是用不同的线程多次运行相同的QObject

这是我的主要任务

from PyQt5.QtCore import *
from PyQt5.QtWidgets import *
import threading
import sys
from Worker_Starting import Worker_Starting


class Main(QMainWindow):
    def __init__(self) :
        super().__init__()
        self.setupUI()
        self.initSignal()

    def setupUI(self):
        self.resize(400, 400)
        self.pushButton = QPushButton("Start", self)
        self.pushButton_2 = QPushButton("Stop", self)
        self.pushButton.move(0,0)
        self.pushButton_2.move(120,0)


    def initSignal(self) :
        self.pushButton.clicked.connect(self.Start)
        self.pushButton_2.clicked.connect(self.Stop)

    @pyqtSlot()
    def Start(self) :
        for i in range(3) :  
            print('main', threading.get_ident())
            input = ["userID", "userNAME"]

            self.my_thread = QThread()
            self.my_worker = Worker_Starting(passing_list=input)
            self.my_worker.moveToThread(self.my_thread)
            self.my_thread.started.connect(self.my_worker.my_fn)
            self.my_thread.start()
            time.sleep(3)


    @pyqtSlot()
    def Stop(self) :
        pass

if __name__ == "__main__":
    app = QApplication(sys.argv)
    window = Main()
    window.show()
    app.exec_()

还有我的对象

from PyQt5 import QtCore
from PyQt5.QtCore import *
import time
import threading

class Worker_Starting(QObject):
    def __init__(self, passing_list, parent=None):
        QtCore.QThread.__init__(self, parent=parent)
        self.userid = passing_list[0]
        self.username = passing_list[1]

    def my_fn(self):
        print(self.username, threading.get_ident())
        for i in range(10) :
            Now = time.strftime("%Y/%m/%d %H:%M:%S")
            print(str(i) + " : " + self.username + "  running" + " : " + Now)
            time.sleep(0.5)

我把for i in range(3):放在def start(self):下面

因为在我的实际主脚本中,其他线程多次向def start(self):发送输入

如果我只发射一次,def start(self):工作正常。 但当我发射几次时,它就会发出尖叫声。 因为我必须发射几次,我需要my_thread同时连续地工作

是否仍要将同一Qobject设置为不同的线程

以及如何知道或设置线程id

以及如何通过线程id停止线程

*我尝试过QRunnable,现在它可以多线程工作。但我必须不断地将信号发射回我的主天线。据我所知,QRunnable不适合定制信号


Tags: fromimportselfinitmydef线程thread
1条回答
网友
1楼 · 发布于 2024-09-28 01:26:59

问题是,您不断地通过覆盖现有线程来创建新线程,这会导致前一个线程在完成之前被垃圾收集,从而导致崩溃

如果要同时执行同一个“worker”函数,则不能对多个线程使用单个对象,因为每次都应使用moveToThread,这是不可能的

解决方案是改用QRunnable,在其run()方法中实现该函数,并调用QThreadPool来运行它

class Worker_Starting(QRunnable):
    def __init__(self, passing_list):
        QRunnable.__init__(self)
        self.setAutoDelete(False)
        self.userid = passing_list[0]
        self.username = passing_list[1]

    def run(self):
        print(self.username, threading.get_ident())
        for i in range(10) :
            Now = time.strftime("%Y/%m/%d %H:%M:%S")
            print(str(i) + " : " + self.username + "  running" + " : " + Now)
            time.sleep(0.5)


class Main(QMainWindow):
    def __init__(self) :
        super().__init__()
        self.setupUI()
        self.initSignal()
        self.worker = None

    # ...

    def Start(self) :
        if not self.worker:
            input = ["userID", "userNAME"]
            self.worker = Worker_Starting(passing_list=input)
        for i in range(3):
            print('main', threading.get_ident())
            QThreadPool.globalInstance().start(self.worker)

请记住,您应该而不是在主Qt线程中使用阻塞函数(这就是为什么我从Start()中删除了time.sleep(3))。如果要定期多次启动函数,请使用QTimer:

        interval = 3000 # interval is in milliseconds
        for i in range(3):
            print('main', threading.get_ident())
            QTimer.singleShot(interval * i, lambda:
                QThreadPool.globalInstance().start(self.worker))

请注意pyqtSlot()装饰器通常仅用于特殊情况和高级实现,因此您应该删除它。还请注意,只有类和常量的名称应该大写,而函数、变量和属性的大小写应该小写(首选startstop,而不是StartStop

相关问题 更多 >

    热门问题