Как создать pyqtsignal через многопоточную задачу - PullRequest
1 голос
/ 24 мая 2019

Я пытаюсь излучать pyqtsignal через многопоточность. Я создал функцию, которая выполняет вычисления (например, func). И еще одна функция, которая выполняет эту задачу и запускает ее в нескольких потоках (например, функция).

Код работает хорошо, когда я использую родительский поток. Но когда я использую несколько потоков, вычисления работают хорошо, но сигнал не излучается.

Мне нужно использовать многопоточность, так как функции, которые я пишу, выполняют дорогостоящие вычислительные задачи.

Ниже приведен пример кода (в этом примере я использовал простую функцию печати)

from PyQt5.QtCore import QObject, pyqtSignal,pyqtSlot
import time
from threading import Thread
import sys
import math
import concurrent.futures


class Plot2D(QObject):
    finish=pyqtSignal(float)

    def __init__(self):
        super(Plot2D,self).__init__()

    def Function(self):
        st = time.time()

        # Using parent thread
        # self.func()

        # Using multi-thread 1
        #t=Thread(target=self.func)
        #t.start()
        #t.join()

        # Using multi-thread 2
        with concurrent.futures.ThreadPoolExecutor(max_workers=3) as executor:
           f = executor.submit(self.func)
        en = time.time()
        print(en-st)

    def func(self):
        n=10
        v=(1*100/(n-1))

        for i in range(n):
            print('thread')
            self.finish.emit(v)

    def fprint(self):
        print('works')

obj=Plot2D()
obj.finish.connect(obj.fprint)
obj.Function()

1 Ответ

0 голосов
/ 24 мая 2019

Вы должны четко понимать следующую концепцию: Сигналы нуждаются в петле событий для работы сигналов.

С учетом вышеизложенного решения:

  • threading.Thread

Не следует использовать join (), потому что он блокирует основной поток, в котором находится цикл обработки событий, и из-за вышеизложенного сигналы не будут работать.

from PyQt5 import QtCore
from threading import Thread


class Plot2D(QtCore.QObject):
    finished = QtCore.pyqtSignal(float)

    def Function(self):
        Thread(target=self.func).start()

    def func(self):
        n = 10
        v = 1 * 100 / (n - 1)

        for i in range(n):
            print("thread")
            self.finished.emit(v)

    @QtCore.pyqtSlot()
    def fprint(self):
        print("works")


if __name__ == "__main__":
    import sys

    app = QtCore.QCoreApplication(sys.argv)
    obj = Plot2D()
    obj.finished.connect(obj.fprint)
    obj.Function()
    sys.exit(app.exec_())

Вывод:

thread
thread
thread
works
thread
works
thread
works
thread
thread
works
thread
works
thread
thread
works
works
works
works
works
  • concurrent.futures

Не использовать с, так как это заставит исполнителя заблокировать основной поток (и мы уже знаем,какую проблему он создает), он также вызывает executor.shutdown(wait = False)

from PyQt5 import QtCore
import concurrent.futures


class Plot2D(QtCore.QObject):
    finished = QtCore.pyqtSignal(float)

    def Function(self):
        executor = concurrent.futures.ThreadPoolExecutor(max_workers=3)
        f = executor.submit(self.func)
        executor.shutdown(wait=False)

    def func(self):
        n = 10
        v = 1 * 100 / (n - 1)

        for i in range(n):
            print("thread")
            self.finished.emit(v)

    @QtCore.pyqtSlot()
    def fprint(self):
        print("works")


if __name__ == "__main__":
    import sys

    app = QtCore.QCoreApplication(sys.argv)
    obj = Plot2D()
    obj.finished.connect(obj.fprint)
    obj.Function()
    sys.exit(app.exec_())

Вывод:

thread
thread
works
thread
works
thread
works
thread
works
thread
thread
works
thread
works
thread
works
thread
works
works
works
...