Не работает остановка и возобновление потоков, что делать? (использовал QWaitCondition())

Не работает остановка и возобновление потоков, что делать? (использовал QWaitCondition())

введите сюда описание изображения

from PyQt5 import QtCore, QtGui, QtWidgets
from PyQt5.QtCore import QThread
from PyQt5.QtWidgets import *
from PyQt5.QtCore import *
import sys
import time

class Ui_Dialog(object):
    def setupUi(self, Dialog):
        Dialog.setObjectName("Dialog")
        Dialog.resize(275, 126)
        self.widget = QtWidgets.QWidget(Dialog)
        self.widget.setGeometry(QtCore.QRect(30, 20, 211, 85))
        self.widget.setObjectName("widget")
        self.horizontalLayout_2 = QtWidgets.QHBoxLayout(self.widget)
        self.horizontalLayout_2.setContentsMargins(0, 0, 0, 0)
        self.horizontalLayout_2.setObjectName("horizontalLayout_2")
        self.verticalLayout = QtWidgets.QVBoxLayout()
        self.verticalLayout.setObjectName("verticalLayout")
        self.comboBox = QtWidgets.QComboBox(self.widget)
        self.comboBox.setObjectName("comboBox")
        self.verticalLayout.addWidget(self.comboBox)
        self.horizontalLayout = QtWidgets.QHBoxLayout()
        self.horizontalLayout.setObjectName("horizontalLayout")
        self.label = QtWidgets.QLabel(self.widget)
        self.label.setObjectName("label")
        self.horizontalLayout.addWidget(self.label)
        self.label_2 = QtWidgets.QLabel(self.widget)
        font = QtGui.QFont()
        font.setPointSize(12)
        self.label_2.setFont(font)
        self.label_2.setText("")
        self.label_2.setObjectName("label_2")
        self.horizontalLayout.addWidget(self.label_2)
        self.verticalLayout.addLayout(self.horizontalLayout)
        self.horizontalLayout_2.addLayout(self.verticalLayout)
        self.verticalLayout_2 = QtWidgets.QVBoxLayout()
        self.verticalLayout_2.setObjectName("verticalLayout_2")
        self.pushButton = QtWidgets.QPushButton(self.widget)
        self.pushButton.setObjectName("pushButton")
        self.verticalLayout_2.addWidget(self.pushButton)
        self.pushButton_2 = QtWidgets.QPushButton(self.widget)
        self.pushButton_2.setObjectName("pushButton_2")
        self.verticalLayout_2.addWidget(self.pushButton_2)
        self.pushButton_3 = QtWidgets.QPushButton(self.widget)
        self.pushButton_3.setObjectName("pushButton_3")
        self.verticalLayout_2.addWidget(self.pushButton_3)
        self.horizontalLayout_2.addLayout(self.verticalLayout_2)

        self.retranslateUi(Dialog)
        QtCore.QMetaObject.connectSlotsByName(Dialog)
        self.show()

    def retranslateUi(self, Dialog):
        _translate = QtCore.QCoreApplication.translate
        Dialog.setWindowTitle(_translate("Dialog", "Dialog"))
        self.label.setText(_translate("Dialog", "Sum:"))
        self.pushButton.setText(_translate("Dialog", "Add"))
        self.pushButton_2.setText(_translate("Dialog", "Pause"))
        self.pushButton_3.setText(_translate("Dialog", "Resume"))


class Thread(QThread):
    def __init__(self):
        QThread.__init__(self)
        self._isPause = False
        self.condition = QWaitCondition()
        self.mutex = QMutex()
        self.sum = 0

    def pause(self):
        self._isPause = True

    def resume(self):
        self._isPause = False
        self.condition.wakeAll()

    def run(self):
        while True:
            self.mutex.lock()
            if self._isPause:
                self.condition.wait(self.mutex)
            self.sum += 1
            time.sleep(2000)
            self.mutex.unlock()

class Window(QDialog, Ui_Dialog):

    def __init__(self):
        super().__init__()
        self.setupUi(self)
        self.threads = []
        self.sum = 0
        self.count = 1
        self.timer = QtCore.QTimer()
        self.timer.timeout.connect(self.update)
        self.timer.start(6000)

        self.pushButton.clicked.connect(self.add)
        self.pushButton_2.clicked.connect(self.stop)
        self.pushButton_3.clicked.connect(self.resume)

    def update(self):
        for i in range(len(self.threads)):
            self.sum += self.threads[i].sum
        self.label_2.setText(str(self.sum))

    def add(self):
        self.thread = Thread()
        self.comboBox.addItem(f'Поток #{self.count}')
        self.thread.start()
        self.threads.append(self.thread)
        self.count += 1

    def stop(self):
        id = self.comboBox.currentIndex()
        self.threads[id].pause()

    def resume(self):
        id = self.comboBox.currentIndex()
        self.threads[id].resume()

if __name__ == '__main__':
    app = QtWidgets.QApplication(sys.argv)
    window = Window()
    sys.exit(app.exec_())

Ответы (1 шт):

Автор решения: gil9red

В классе Thread поменяйте задержку, на меньшую:

    def run(self):
        while True:
            self.mutex.lock()
            if self._isPause:
                self.condition.wait(self.mutex)
            self.sum += 1
            time.sleep(2)
#                  ^^^^^^^^^
            self.mutex.unlock()

В Window на каждое обновление нужно сбрасывать значение self.sum:

    def update(self):
        self.sum = 0
#       ^^^^^^^^^^^^
        for i in range(len(self.threads)):
            self.sum += self.threads[i].sum
        self.label_2.setText(str(self.sum))

Весь код (с рефакторингом):

from PyQt5 import QtCore, QtGui, QtWidgets
from PyQt5.QtCore import QThread
from PyQt5.QtWidgets import *
from PyQt5.QtCore import *
import sys
import time

class Ui_Dialog(object):
    def setupUi(self, Dialog):
        Dialog.setObjectName("Dialog")
        Dialog.resize(275, 126)
        self.widget = QtWidgets.QWidget(Dialog)
        self.widget.setGeometry(QtCore.QRect(30, 20, 211, 85))
        self.widget.setObjectName("widget")
        self.horizontalLayout_2 = QtWidgets.QHBoxLayout(self.widget)
        self.horizontalLayout_2.setContentsMargins(0, 0, 0, 0)
        self.horizontalLayout_2.setObjectName("horizontalLayout_2")
        self.verticalLayout = QtWidgets.QVBoxLayout()
        self.verticalLayout.setObjectName("verticalLayout")
        self.comboBox = QtWidgets.QComboBox(self.widget)
        self.comboBox.setObjectName("comboBox")
        self.verticalLayout.addWidget(self.comboBox)
        self.horizontalLayout = QtWidgets.QHBoxLayout()
        self.horizontalLayout.setObjectName("horizontalLayout")
        self.label = QtWidgets.QLabel(self.widget)
        self.label.setObjectName("label")
        self.horizontalLayout.addWidget(self.label)
        self.label_2 = QtWidgets.QLabel(self.widget)
        font = QtGui.QFont()
        font.setPointSize(12)
        self.label_2.setFont(font)
        self.label_2.setText("")
        self.label_2.setObjectName("label_2")
        self.horizontalLayout.addWidget(self.label_2)
        self.verticalLayout.addLayout(self.horizontalLayout)
        self.horizontalLayout_2.addLayout(self.verticalLayout)
        self.verticalLayout_2 = QtWidgets.QVBoxLayout()
        self.verticalLayout_2.setObjectName("verticalLayout_2")
        self.pushButton = QtWidgets.QPushButton(self.widget)
        self.pushButton.setObjectName("pushButton")
        self.verticalLayout_2.addWidget(self.pushButton)
        self.pushButton_2 = QtWidgets.QPushButton(self.widget)
        self.pushButton_2.setObjectName("pushButton_2")
        self.verticalLayout_2.addWidget(self.pushButton_2)
        self.pushButton_3 = QtWidgets.QPushButton(self.widget)
        self.pushButton_3.setObjectName("pushButton_3")
        self.verticalLayout_2.addWidget(self.pushButton_3)
        self.horizontalLayout_2.addLayout(self.verticalLayout_2)

        self.retranslateUi(Dialog)
        QtCore.QMetaObject.connectSlotsByName(Dialog)

    def retranslateUi(self, Dialog):
        _translate = QtCore.QCoreApplication.translate
        Dialog.setWindowTitle(_translate("Dialog", "Dialog"))
        self.label.setText(_translate("Dialog", "Sum:"))
        self.pushButton.setText(_translate("Dialog", "Add"))
        self.pushButton_2.setText(_translate("Dialog", "Pause"))
        self.pushButton_3.setText(_translate("Dialog", "Resume"))


class Thread(QThread):
    def __init__(self, parent=None):
        super().__init__(parent)
        self._isPause = False
        self.condition = QWaitCondition()
        self.mutex = QMutex()
        self.sum = 0

    def pause(self):
        self._isPause = True

    def resume(self):
        self._isPause = False
        self.condition.wakeAll()

    def run(self):
        while True:
            self.mutex.lock()
            if self._isPause:
                self.condition.wait(self.mutex)
            self.sum += 1
            time.sleep(2)
            self.mutex.unlock()


class Window(QDialog, Ui_Dialog):
    def __init__(self):
        super().__init__()
        self.setupUi(self)

        self.threads = []
        self.sum = 0
        self.count = 1
        self.timer = QtCore.QTimer()
        self.timer.timeout.connect(self.update)
        self.timer.start(1000)

        self.pushButton.clicked.connect(self.add)
        self.pushButton_2.clicked.connect(self.stop)
        self.pushButton_3.clicked.connect(self.resume)

    def update(self):
        self.sum = sum(thread.sum for thread in self.threads)
        self.label_2.setText(str(self.sum))

    def add(self):
        thread = Thread(self)
        self.comboBox.addItem(f'Поток #{self.count}')
        thread.start()
        self.threads.append(thread)
        self.count += 1

    def stop(self):
        id = self.comboBox.currentIndex()
        self.threads[id].pause()

    def resume(self):
        id = self.comboBox.currentIndex()
        self.threads[id].resume()


if __name__ == '__main__':
    app = QtWidgets.QApplication(sys.argv)

    window = Window()
    window.show()

    sys.exit(app.exec_())
→ Ссылка