Одновременное выполнение двух потоков
У меня есть программа которая должна выполнять ряд функций одновременно в разных потоках, но при одновременном запуске этих функций программа крашится.
Написал простой пример как я запускаю эти функции:
from PyQt5.QtCore import QCoreApplication, QObject, QRunnable, QThread, QThreadPool, pyqtSignal, pyqtSlot
from PyQt5 import Qt
import sys
import time
class MainWindow(Qt.QWidget):
def __init__(self, parent=None):
super(MainWindow, self).__init__(parent)
layout = Qt.QVBoxLayout(self)
self.lblA = Qt.QLabel("Итог выполения первого потока")
layout.addWidget(self.lblA)
self.btnA = Qt.QPushButton("Запустить первый поток")
layout.addWidget(self.btnA)
self.lblB = Qt.QLabel("Итог выполения второго потока")
layout.addWidget(self.lblB)
self.btnB = Qt.QPushButton("Запустить второй поток")
layout.addWidget(self.btnB)
self.init_ui()
def init_ui(self):
self.btnA.clicked.connect(self.thread_one)
self.btnB.clicked.connect(self.thread_two)
def thread_one(self):
self.object_thread = MultiOne()
self.multithreading = QThread()
self.object_thread.moveToThread(self.multithreading)
self.multithreading.started.connect(self.object_thread.example_function)
self.object_thread.finished.connect(self.multithreading.quit)
self.object_thread.finished.connect(self.fill_lblA)
self.multithreading.start()
def thread_two(self):
self.object_thread = MultiTwo()
self.multithreading = QThread()
self.object_thread.moveToThread(self.multithreading)
self.multithreading.started.connect(self.object_thread.example_function)
self.object_thread.finished.connect(self.multithreading.quit)
self.object_thread.finished.connect(self.fill_lblB)
self.multithreading.start()
def fill_lblA(self, text):
self.lblA.setText(text)
def fill_lblB(self, text):
self.lblB.setText(text)
class MultiOne(QObject):
finished = pyqtSignal(str)
def __init__(self):
super(MultiOne, self).__init__()
def example_function(self):
i = 0
while i < 10:
i += 1
time.sleep(0.5)
self.finished.emit(f'Ура! Первая функция отработала')
class MultiTwo(QObject):
finished = pyqtSignal(str)
def __init__(self):
super(MultiTwo, self).__init__()
def example_function(self):
i = 0
while i < 5:
i += 1
time.sleep(0.5)
self.finished.emit(f'Ура! Вторая функция отработала')
if __name__ == '__main__':
app = Qt.QApplication([])
application = MainWindow()
application.show()
sys.exit(app.exec())
В моем примере если нажать первую или вторую кнопку и дождаться выполнения, то все работает корректно, но если нажать сразу обе кнопки, то программа крашится.
Я понимаю что скорее всего пытаюсь в уже запущенный поток поместить другой объект и из-за это происходит ошибка. Как правильно запустить второй поток для выполнения второй функции? Я понимаю что есть способ создать класс с наследованием от QThread, переопределить функцию run и сделать это для каждой функции, но есть ли способы с наследованием от QObject и помещением объекта в поток?
В оригинале программы в потоках выполняется обработка SQL и Postman запросов.
Ответы (1 шт):
Нехорошо, что вы используете одну переменную для хранения разных объектов:
def thread_one(self):
self.object_thread = MultiOne()
self.multithreading = QThread()
...
def thread_two(self):
self.object_thread = MultiTwo()
self.multithreading = QThread()
Представим ситуацию:
- Вы создали объект
MultiOneи QThread при запуске первой кнопки - Объекты живут и работают
- После вы запустили вторую кнопку и переписали переменные, а это значит, что на эти объекты пропали ссылки, тогда их нужно удалить
- Но логика запущена, а объектов нет - ошибка
Поэтому, вижу такие решения:
1. Разные переменные для объектов
def thread_one(self):
self.object_thread_1 = MultiOne()
self.multithreading_1 = QThread()
self.object_thread_1.moveToThread(self.multithreading_1)
self.multithreading_1.started.connect(self.object_thread_1.example_function)
self.object_thread_1.finished.connect(self.multithreading_1.quit)
self.object_thread_1.finished.connect(self.fill_lblA)
self.multithreading_1.start()
def thread_two(self):
self.object_thread_2 = MultiTwo()
self.multithreading_2 = QThread()
self.object_thread_2.moveToThread(self.multithreading_2)
self.multithreading_2.started.connect(self.object_thread_2.example_function)
self.object_thread_2.finished.connect(self.multithreading_2.quit)
self.object_thread_2.finished.connect(self.fill_lblB)
self.multithreading_2.start()
2. Добавление ссылки на объект, путем указания родителя потока
В обе функции укажите:
self.multithreading = QThread(self)