【问题标题】:How to use QThread for data transfer between child threads?如何使用 QThread 进行子线程之间的数据传输?
【发布时间】:2020-11-20 15:09:25
【问题描述】:

我想在 Pyside2 中使用 QThread 在子线程之间传输数据。我想在readThread(子线程)中写一个APP读取串口数据,在writeThread(子线程)中写入读取的数据,并在plot函数(主线程)中绘制串口数据。为此我写了一个demo,代码如下:

import threading
from PySide2.QtWidgets import QApplication, QPushButton, QWidget, QVBoxLayout, QLCDNumber, QMessageBox
from PySide2.QtCore import *
import sys
import os

# add environment path of pyside2
envpath = r'E:\anaconda\envs\tensorflow\Lib\site-packages\PySide2\plugins\platforms'
os.environ["QT_QPA_PLATFORM_PLUGIN_PATH"] = envpath

sec = 0    # counter 

# child thread, representing the process of read serial data
class ReadThread(QThread):
        timer = Signal()  # create a signal
        end = Signal()  # create a signal
    
        def run(self):
            print("ReadThread1", threading.current_thread())  # print thread ID
            while True:
                self.sleep(1)  # sleep 1s
                print("ReadThread2", threading.current_thread())  
                if sec == 2:
                    self.end.emit()  # emit end signal
                    break
                self.timer.emit()
    
# chiald thead2, represents write data to txt file
class WriteThread(QThread):
    
        def run(self):
            print("WriteThread", threading.current_thread())  # print thread ID
    
class Counter(QWidget):
    
        def __init__(self, parent=None):
            super(Counter, self).__init__(parent)
    
            self.setWindowTitle("qthreading test")
            self.resize(300, 120)
    
            # add a layout
            layout = QVBoxLayout()
            self.lcdNumber = QLCDNumber()
            layout.addWidget(self.lcdNumber)
            # add a pushbutton 
            button = QPushButton('start')
            layout.addWidget(button)
    
            self.readThread = ReadThread()  # workthread
            self.writeThread = WriteThread()  # writeThread
            self.readThread.timer.connect(self.plot)   
    
            self.readThread.timer.connect(self.writeThread.run) #I want to connect readThread and writeThread
    
            self.readThread.end.connect(self.end)
    
            button.clicked.connect(self.work)
    
            self.setLayout(layout)
    
        # The callback function of readThread (Main Thread), representing the process of plot serial data
        def plot(self):
            global sec
            sec += 1
            self.lcdNumber.display(sec)
            print("countTime", threading.current_thread())  
    
        def end(self):
            QMessageBox.information(self, "message", "stop")
    
        # start readTread and WriteThread when button is clicked
        def work(self):
            self.readThread.start()
            self.writeThread.start()  
    
    
if __name__ == "__main__":
    app = QApplication(sys.argv)
    form = Counter()
    form.show()
    sys.exit(app.exec_())

当我运行程序时,输出如下:

**ReadThread1 <_DummyThread(Dummy-1, started daemon 7556)>
WriteThread <_DummyThread(Dummy-2, started daemon 2552)>
ReadThread2 <_DummyThread(Dummy-1, started daemon 7556)>
WriteThread <_MainThread(MainThread, started 7536)>
ReadThread2 <_DummyThread(Dummy-1, started daemon 7556)>
WriteThread <_MainThread(MainThread, started 7536)>
ReadThread2 <_DummyThread(Dummy-1, started daemon 7556)>**

如您所见,起初 readThread 和 writeThread 都在子线程中,但随着 signal() 的发出,writeThread 在主线程中运行,而 readThread 在子线程中。我不知道我的代码有什么问题。为什么writeThread响应signal()时操作没有在子线程中完成?如果你能直接在我的代码中修改就好了。

【问题讨论】:

    标签: python multithreading qthread pyside2


    【解决方案1】:

    您的逻辑中有一个基本错误:您不应该直接调用 QThread 的 run 方法,因为它是由 start 方法间接调用的,因此您注意到一开始“run”方法是在辅助线程中执行的线程,然后当你直接调用它时,它将在QObject(WriteThread)所属的线程中执行,也就是主线程。

    如果您想根据信号在辅助线程中执行任务,则必须创建一个 QObject 并将其移动到新线程:

    class ReadThread(QThread):
        timer = Signal()  # create a signal
        end = Signal()  # create a signal
    
        def run(self):
            print("ReadThread1", threading.current_thread())  # print thread ID
            while True:
                self.sleep(1)  # sleep 1s
                print("ReadThread2", threading.current_thread())
                if sec == 2:
                    self.end.emit()  # emit end signal
                    break
                self.timer.emit()
    
    
    class WriteWorker(QObject):
        def run_task(self):
            print("WriteThread", threading.current_thread())
    
    
    class Counter(QWidget):
        def __init__(self, parent=None):
            super(Counter, self).__init__(parent)
    
            self.setWindowTitle("qthreading test")
            self.resize(300, 120)
    
            # add a layout
            layout = QVBoxLayout()
            self.lcdNumber = QLCDNumber()
            layout.addWidget(self.lcdNumber)
            # add a pushbutton
            button = QPushButton("start")
            layout.addWidget(button)
    
            self.readThread = ReadThread()  # workthread
            self.writeThread = QThread()  # writeThread
            self.readThread.timer.connect(self.plot)
    
            self.worker = WriteWorker()
            self.worker.moveToThread(self.writeThread)
    
            self.readThread.timer.connect(self.worker.run_task)
    
            self.readThread.end.connect(self.end)
    
            button.clicked.connect(self.work)
    
            self.setLayout(layout)
    
        def plot(self):
            global sec
            sec += 1
            self.lcdNumber.display(sec)
            print("countTime", threading.current_thread())
    
        def end(self):
            QMessageBox.information(self, "message", "stop")
    
        def work(self):
            self.readThread.start()
            self.writeThread.start()
    
    
    if __name__ == "__main__":
        app = QApplication(sys.argv)
        form = Counter()
        form.show()
        ret = app.exec_()
        form.writeThread.quit()
        form.writeThread.wait()
        sys.exit(ret)
    

    输出:

    ReadThread1 <_DummyThread(Dummy-1, started daemon 140088050697792)>
    ReadThread2 <_DummyThread(Dummy-1, started daemon 140088050697792)>
    WriteThread <_DummyThread(Dummy-2, started daemon 140088042305088)>
    countTime <_MainThread(MainThread, started 140088409069376)>
    ReadThread2 <_DummyThread(Dummy-1, started daemon 140088050697792)>
    countTime <_MainThread(MainThread, started 140088409069376)>
    WriteThread <_DummyThread(Dummy-2, started daemon 140088042305088)>
    ReadThread2 <_DummyThread(Dummy-1, started daemon 140088050697792)>
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-07-23
      • 1970-01-01
      • 2023-04-01
      • 2012-04-09
      • 1970-01-01
      • 1970-01-01
      • 2016-11-27
      • 1970-01-01
      相关资源
      最近更新 更多