首页 > 解决方案 > 线程功能块 main 并非一直如此

问题描述

我正在开发一个项目,其中我有一个主类,它创建一个线程来执行一个很长的函数,而主类(我的 GUI)将继续可用于在执行这个长函数期间显示一些信息。所以我在 Stack Overflow 上找到了一种方法:

from PyQt5 import QtWidgets, QtCore, QtGui
from PyQt5.QtWidgets import QApplication
import threading
import sys
import time
from PyQt5.QtCore import QObject, pyqtSignal


class Ui_SaftMainWindow(object):
    def setupUi(self, SaftMainWindow):
        SaftMainWindow.setObjectName("SaftMainWindow")
        SaftMainWindow.resize(178, 284)
        icon = QtGui.QIcon()
        icon.addPixmap(QtGui.QPixmap(":/logo/img_Logo-E.png"), QtGui.QIcon.Normal, QtGui.QIcon.Off)
        SaftMainWindow.setWindowIcon(icon)
        self.gridLayout = QtWidgets.QGridLayout(SaftMainWindow)
        self.gridLayout.setObjectName("gridLayout")
        self.frame_all_pb = QtWidgets.QFrame(SaftMainWindow)
        self.frame_all_pb.setMinimumSize(QtCore.QSize(160, 0))
        self.frame_all_pb.setMaximumSize(QtCore.QSize(160, 16777215))
        self.frame_all_pb.setObjectName("frame_all_pb")
        self.gridLayout_7 = QtWidgets.QGridLayout(self.frame_all_pb)
        self.gridLayout_7.setObjectName("gridLayout_7")
        self.pb_stop_simu = QtWidgets.QPushButton(self.frame_all_pb)
        self.pb_stop_simu.setText("STOP")
        self.gridLayout_7.addWidget(self.pb_stop_simu, 5, 0, 1, 1)
        self.pb_start_simu = QtWidgets.QPushButton(self.frame_all_pb)
        self.pb_start_simu.setObjectName("pb_start_simu")
        self.pb_start_simu.setText("START")
        self.gridLayout_7.addWidget(self.pb_start_simu, 4, 0, 1, 1)
        self.gridLayout.addWidget(self.frame_all_pb, 0, 0, 1, 1)

        QtCore.QMetaObject.connectSlotsByName(SaftMainWindow)


class Solver(QObject, object):
    data_changed = pyqtSignal(str, int)

    def __init__(self):
        # Call init function of QObject class for pyQt signal
        QObject.__init__(self)


    def init_parameters(self, input_files, **keys):
        print("Some initialisation")

    def time_step(self):
        # Function with Fortran call
        print("Fortran function")

    def transient_solve(self, arg):
        print("starting")
        t = threading.currentThread()
        i = 1
        while getattr(t, "do_run", True):
            print("working on " + str(i))
            i += 1
            time.sleep(5)
        print("Stopping as you wish.")


class GuiHandler:
    def __init__(self, gui, main_window,):
        # Declarations
        self.gui = gui
        self.main_window = main_window

        self.gui.setupUi(self.main_window)
        self.gui.pb_start_simu.clicked.connect(self.pb_start_simu_clicked)
        self.gui.pb_stop_simu.clicked.connect(self.pb_stop_simu_clicked)

        # Create instance of the second class
        app = Solver()

        # Connect signal to emit signal from second class to ihm later
        app.data_changed.connect(self.myfunction)

        # Initialize some parameters of my second class
        app.init_parameters("", json_file="", output_file="")

        # Create thread object
        self.t = threading.Thread(target=app.transient_solve, args=("task",))

    def pb_start_simu_clicked(self):
        print("Start thread")
        self.t.start()

    def pb_stop_simu_clicked(self):
        print("Stop thread")
        self.t.do_run = False
        self.t.join()

    def myfunction(self, string="this_is_a_test", integer=0):
        print(str(string))
        print(str(integer))


if __name__ == "__main__":
    app = QApplication(sys.argv)
    handler = GuiHandler(Ui_SaftMainWindow(), QtWidgets.QWidget())
    handler.main_window.show()
    sys.exit(app.exec_())

这个简单的例子有效。但是,当我通过调用更大的函数来替换睡眠时(调用编译为 Python 的 Fortran 文件的 time_step 函数,GUI 函数被阻止)

是否知道它是否与我创建和启动线程的方式相关联,或者关于我必须检查/查找的内容才能使我的代码工作的任何想法?

我现在不能给你另一个代码示例。

标签: pythonmultithreadingnonblocking

解决方案


我找到了一个解决方案,添加!f2py: threadsafe了 fortran 代码。


推荐阅读