QThread-更改全局列表中的数据-不同的值

时间:2019-07-08 19:45:16

标签: locking pyqt5 qthread

我正在使用QThread进行一些时间密集的计算,以防止GUI冻结。在QThread中,我在线程生命周期中多次访问和更改全局列表,但是我无法获得与仅在主线程上相同的结果。

我认为您必须执行某种锁定,但是我对QThread并不陌生,也不知道如何实现它。

#Main Thread
                    self.runGasAnalysisThread = GasAnalysisThread()
                    self.runGasAnalysisThread.start()

#QThread
class GasAnalysisThread(QtCore.QThread):
    """Performs gas analysis function"""
    def __init__(self,parent = None):
        super().__init__(parent)

    def run(self):
        try:
            boolValue = True
            while True:
               #Change lists here
               float(Data.TestList[0])+ 1 #Data is another module I am using to store variables

同样,将代码移到主线程上也可以正常工作,但是一旦我使用QThread进行操作,我就会得到不同的结果。

我将如何实现锁定机制以防止这种情况发生?

1 个答案:

答案 0 :(得分:0)

使用Qt的线程时经常会感到困惑,因为人们会认为子类化QThread是正确的路径。
事实是,QThread是实际运行进程的Qt线程对象,这意味着您需要一个单独的类,并在QThread中将其 move 实例 。通常不需要对QThread进行子类化。
如果您需要“工人”(执行处理的对象)与主线程(如GUI中)之间的任何形式的交互,则使用Qt的信号是一种很好的做法。

在此示例中,我使用按钮来启动处理,一旦处理器启动,它将禁用该按钮,并在信号指示该过程完成后重新启用它。

class Worker(QtCore.QObject):
    stateChanged = QtCore.pyqtSignal(bool)

    def __init__(self):
        super().__init__()

    def run(self):
        self.stateChanged.emit(True)
        try:
            boolValue = True
            while True:
               # this doesn't make much sense, as it doesn't seem to do anything;
               # I'll leave it just for the sake of the argument
               float(Data.TestList[0]) + 1
        except:
            pass
        self.stateChanged.emit(False)

class SomeWidget(QtWidgets.QWidget):
    def __init__(self, parent=None):
        super().__init__(parent)
        layout = QtWidgets.QHBoxLayout()
        self.setLayout(layout)
        self.startButton = QtWidgets.QPushButton('Start')
        layout.addWidget(self.startButton)

        self.worker = Worker()
        self.workerThread = QtCore.QThread()
        self.worker.moveToThread(self.workerThread)
        self.workerThread.started.connect(self.worker.run)

        self.startButton.clicked.connect(self.workerThread.start)
        self.worker.stateChanged.connect(self.startButton.setDisabled)