Многопоточная программа PyQt на основе QRunnable не работает должным образом - PullRequest
0 голосов
/ 01 апреля 2020

В этой небольшой программе на основе PyQt я создал счетчик от 0 до 10 за 10 секунд. Хотя я использую QRunnable для запуска счетчика в countBox() в отдельном потоке, но после нажатия кнопки пуска GUI перестает отвечать, и счетчик вообще не работает. Ты хоть представляешь, что с этим не так? Спасибо.

from PyQt5.QtGui import *
from PyQt5.QtWidgets import QApplication, QMainWindow, QWidget, QGridLayout, QVBoxLayout, QHBoxLayout, QLineEdit, QPushButton, QLabel
from PyQt5.QtCore import Qt, QRunnable, pyqtSlot, QThreadPool

import time, sys

class Worker(QRunnable):
    def __init__(self, fn, *args, **kwargs):
        super(Worker, self).__init__()
        self.fn = fn
        self.args = args
        self.kwargs = kwargs

    @pyqtSlot()
    def run(self):
        self.fn(*self.args, **self.kwargs)

def createCounterWorker():
    threadpool = QThreadPool()
    worker = Worker(countBox)
    threadpool.start(worker)

def countBox():
    i = 0
    while i < 10:
        print(f'i: {i}')
        time.sleep(1.0)
        i += 1

class Counter():
    def __init__(self, layout):
        self.startButton = QPushButton(f'Start')
        self.startButton.pressed.connect(lambda: createCounterWorker())
        layout.addWidget(self.startButton)

class MainWindow(QMainWindow):
    def __init__(self, *args, **kwargs):
        super(MainWindow, self).__init__(*args, **kwargs)

        self.layout = QVBoxLayout()

        self.btn = QPushButton('+')
        self.btn.pressed.connect(lambda: self.addNewCounter())
        self.layout.addWidget(self.btn)

        w = QWidget()
        w.setLayout(self.layout)
        self.setCentralWidget(w)
        self.show()

    def addNewCounter(self):
        newCount = Counter(self.layout)

app = QApplication([])
window = MainWindow()

sys.exit(app.exec_())

1 Ответ

1 голос
/ 01 апреля 2020

Проблема проста: threadpool - это объект, который создает потоки, это локальная переменная, которая будет мгновенно уничтожена вместе с потоками, поэтому countBox будет выполняться в главном потоке, что приведет к зависанию GUI, поэтому решение состоит в том, чтобы расширить жизненный цикл этой переменной, чтобы были следующие параметры:

  • Сделать пул потоков глобальной переменной:

    <b>threadpool = QThreadPool()</b>
    
    def createCounterWorker():
        worker = Worker(countBox)
        threadpool.start(worker)
  • Использовать QThreadPool.globalInstance ():

    def createCounterWorker():
        worker = Worker(countBox)
        <b>QThreadPool.globalInstance().start(worker)</b>
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...