@topiq

Как правильно работать с QThread?

Python 3.4, PyQt 4.8, Windows 10

Есть основной поток, в котором работает сама программа. Внутри этого потока мне надо запустить новый поток в фоновом режиме, чтоб основной поток не замораживался (Этот основной поток отвечает за работу с GUI). Из фонового потока нужно менять некоторые элементы GUI. Делал всё следующим образом:

В основной форме:
self.connect(self.pushButton_4,QtCore.SIGNAL("clicked()"),self.addAllAccounts)
...
...
def addAllAccounts(self):
      print("pushButton_4 нажата")
        login,password,name=[],[],[]
        #Здесь пропущен для удобства кусок, в котором я заполняю login, password, name
        #Если массив логинов не пустой, запускаю отдельный тред
        if login:
            self.pushButton_4.setEnabled(False) #Блокирую кнопку
            self.runnable = AThread(login,password,name)
            self.runnable.progressed.connect(self.progressBarHandler)
            self.runnable.finished.connect(app.exit)
            self.runnable.start()
            self.label_43.setText("Подождите, добавление займет некоторое время...")
            self.progressBar.setMinimum(0)    
            self.progressBar.setMaximum(len(name))
            self.progressBar.setValue(0)
            self.progressBar.show()
            self.label_43.show()
           #Проблема вот в этой строчке
            self.runnable.wait() #Если её не использовать, программа падает в случайном месте
           #не выдавая ошибок; Если её использовать,  GUI замораживается и программа 
           #  подвисает, пока работает фоновый поток


Что я делаю не так? AThread наследуется от QThread, в нем переписан метод run(). Выглядит оно вот так:
class AThread(QtCore.QThread):
    progressed = pyqtSignal()

    def __init__(self,logins,passwords,names):
        super(AThread,self).__init__()
        self.logins=logins
        self.passwords=passwords
        self.names=names
        
    def run(self):
        print(self.logins)
        print(self.passwords)
        print(self.names)
        for i in range(0,len(self.logins)):
            login = self.logins[i]
            password = self.passwords[i]
            name = self.names[i]
            checkResult = vk.checkIfValid(login,password)
           self.progressed.emit()


В основной программе на сигнал progressed повешен обработчик, который работает с GUI.

Проблема в том, что программа крашится, если не использовать runnable.wait() в основном потоке. А если использовать, то GUI подвисает.
  • Вопрос задан
  • 715 просмотров
Пригласить эксперта
Ответы на вопрос 2
В Qt есть абстракция над потоками QtConcurrent. В ней есть метод run. Куда можно забросить метод, который вы хотите выполнить асинхронно. run вернет вам QtFuture. Через него мы можем узнать, что сейчас происходит с нашим потоком(завершился или еще работает). QtFuture можно передать в QtFutureWatcher в котрого есть сигнал finished, который стрельнет когда функция завершить свою работу.

Преимуществом данного подхода является, то что Qt берет на себя всю волокиту с созданием и управлением потоков.
Ответ написан
Комментировать
Используйте сообщения Windows через Api функции SendMessage/PostMessage для взаимодействия между потоками.
Ответ написан
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы