Возврат значения в рабочий поток
Всем привет.
Каким образом можно отправить ответ от QMessageBox из главного потока приложения в рабочий?
Есть кнопка, при нажатии которой запускается второй поток, там выполняется какая-нибудь операция. При завершении операции отправляется сигнал в главный поток, в котором пользователю выводится сообщение.
При нажатии на кнопку "Нет" рабочий поток останавливается и все(тут проблем нет), но как отправить ответ во второй поток, если пользователь нажал на кнопку "Да"?
При нажатии на "Да", во втором потоке должна выполниться операция 2.
class ThreadClass(QThread):
"""
Класс рабочего потока
"""
questSignal = pyqtSignal(str) # Для хранения ответа на вопрос об обновлении
def __init__(self):
super().__init__()
def run(self):
# Выполняется операция 1
print('Операция 1')
# Далее генерируется сигнал и в главном окне появляется вопрос (Да/Нет)
self.questSignal.emit('1')
print('Дождаться ответа от qmessagebox')
# Если ответ Да, то выполняется операция 2, если ответ Нет, то стоп.
Часть кода из главного окна приложения
def start_worker(self):
"""
Работа кнопки Проверить обновления
"""
self.workerThread = ThreadClass()
self.workerThread.questSignal.connect(self.on_changed, Qt.QueuedConnection)
self.workerThread.start() # Запуск рабочего потока
def on_changed(self, res):
"""
Получает ответ от рабочего потока
"""
reply = QMessageBox.question(self, 'Обновление','Обновить файлы?',
QMessageBox.Yes | QMessageBox.No)
if reply == QMessageBox.Yes:
print('Вернуть значение в рабочий поток')
if reply == QMessageBox.No:
self.workerThread.terminate()
Ответы (2 шт):
Надо приостановить поток при помощи QWaitCondition и блокировки залоченого мьютекса (QMutex):
class ThreadClass(QThread):
"""
Класс рабочего потока
"""
questSignal = pyqtSignal(str) # Для хранения ответа на вопрос об обновлении
def __init__(self):
super().__init__()
self.waiter = QWaitCondition()
self.answer = false;
def run(self):
# Выполняется операция 1
print('Операция 1')
mutex = QMutex()
# Далее генерируется сигнал и в главном окне появляется вопрос (Да/Нет)
self.questSignal.emit('1')
print('Дождаться ответа от qmessagebox')
mutex.lock()
self.waiter.wait(mutex)
mutex.unlock()
# Если ответ Да, то выполняется операция 2, если ответ Нет, то стоп.
if self.answer:
...
else:
...
def setAnswer(self, value):
self.answer = value
# Будим поток для продолжения работы
self.waiter.wakeAll()
Теперь в методе on_change():
if reply == QMessageBox.Yes:
self.messageBoxAnswerSignal.emit(true)
if reply == QMessageBox.No:
self.messageBoxAnswerSignal.emit(false)
Где-то ранее надо объявить сигнал и соединить его с потоком (терминировать поток не нужно):
self.messageBoxAnswerSignal.connect(self.workerThread.setAnswer)
В дополнение к ответу, который мне дали. Такой код у меня получился. Может кому-то будет полезен. Если что-то не правильно написал, пожалуйста, скажите.
class ThreadClass(QThread):
"""
Класс рабочего потока
"""
resSignal = pyqtSignal(str) # Для хранения успешного или неуспешного рез-та
questSignal = pyqtSignal(str) # Для хранения ответа на вопрос об обновлении
messageBoxAnswerSignal = pyqtSignal(bool)
def __init__(self):
super().__init__()
self.waiter = QWaitCondition()
self.answer = False
def run(self):
print('Операция 1')
self.questSignal.emit('1')
mutex = QMutex()
# Далее генерируется сигнал и в главном окне появляется вопрос (Да/Нет)
mutex.lock()
self.waiter.wait(mutex)
mutex.unlock()
# Если ответ Да, то выполняется операция 2, если ответ Нет, то стоп.
if self.answer:
print('Операция 2')
print('Yes')
else:
print('No')
def setAnswer(self, value):
self.answer = value
# Будим поток для продолжения работы
self.waiter.wakeAll()
Код главного потока, который запускает рабочий поток и назначает обработчики
def start_worker(self):
"""
Работа кнопки Проверить обновления
"""
self.workerThread = ThreadClass()
self.workerThread.resSignal.connect(self.end_work, Qt.QueuedConnection)
self.workerThread.questSignal.connect(self.on_changed, Qt.QueuedConnection)
self.workerThread.messageBoxAnswerSignal.connect(self.workerThread.setAnswer)
self.workerThread.start()
Код главного потока, который вызывает окно QMessageBox и отправляет сигнал в рабочий поток
def on_changed(self, res):
"""
Получает ответ от рабочего потока
"""
reply = QMessageBox.question(self, 'Обновление','Обновить файлы?',
QMessageBox.Yes | QMessageBox.No)
if reply == QMessageBox.Yes:
self.workerThread.messageBoxAnswerSignal.emit(True)
print('Вернуть значение в рабочий поток')
if reply == QMessageBox.No:
self.workerThread.messageBoxAnswerSignal.emit(False)