Multithreading PyQt:如果进程运行太长,如何使用Qthread使其可停止

Multithreading PyQt:如果进程运行太长,如何使用Qthread使其可停止,multithreading,qt,pyqt,scipy,multiprocessing,Multithreading,Qt,Pyqt,Scipy,Multiprocessing,我读了很多关于线程的文章,但我真的需要这方面的帮助: 我有一个PyQt主GUI,它使用scipy运行优化。最小化。。。 因为我不能举例说明,所以我使用了占位符过程 来说明我的问题是什么 我想让主GUI保持可由用户停止,如果这个过程需要太长时间 结果。 我的工作示例是这样一个,其中我使用了与Symphy的集成 import sympy as sp import numpy as np import matplotlib.pyplot as plt import time, sys from PyQ

我读了很多关于线程的文章,但我真的需要这方面的帮助: 我有一个PyQt主GUI,它使用scipy运行优化。最小化。。。 因为我不能举例说明,所以我使用了占位符过程 来说明我的问题是什么

我想让主GUI保持可由用户停止,如果这个过程需要太长时间 结果。 我的工作示例是这样一个,其中我使用了与Symphy的集成

import sympy as sp
import numpy as np
import matplotlib.pyplot as plt
import time, sys
from PyQt4.QtCore  import *
from PyQt4.QtGui import *

class IntegrationRunner(QObject):
    'Object managing the integration'

    def __init__(self):
        super(IntegrationRunner, self).__init__() 
        self._isRunning = True

    def longRunning(self):      
        # reset
        if not self._isRunning:
            self._isRunning = True  

        print("preparing Integration")
        #this is known to be time consuming and returning not the right integral
        #this is a placeholder for a "time consuming" operation that sould 
        #be handled by a thread outside the main GUI
        #imagine an optimization process or any other time consuming operation
        #that would freeze the Main GUI

        t=sp.symbols('t')
        exp=sp.sqrt((3*t+1)/t)
        sol=sp.integrate(exp,t)
        print(sol)

        print('finished...') 

    def stop(self):
        self._isRunning = False
        #this is displayed when the "stop button" is clicked 
        #but actually the integration process won´t stop
        print("Integration too long - User terminated")

class SimulationUi(QDialog):
    'PyQt interface'

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

        self.goButton = QPushButton('Run Integration')
        self.stopButton = QPushButton('Stop if too long')


        self.layout = QHBoxLayout()
        self.layout.addWidget(self.goButton)
        self.layout.addWidget(self.stopButton)

        self.setLayout(self.layout)

        self.simulThread = QThread()
        self.simulThread.start()

        self.simulIntegration = IntegrationRunner()
        self.simulIntegration.moveToThread(self.simulThread)
        #self.simulIntegration.stepIncreased.connect(self.currentStep.setValue)

        # call stop on Integr.Runner from this (main) thread on click
        self.stopButton.clicked.connect(lambda: self.simulIntegration.stop())
        self.goButton.clicked.connect(self.simulIntegration.longRunning)

if __name__ == '__main__':
    app = QApplication(sys.argv)
    simul = SimulationUi()
    simul.show()
    sys.exit(app.exec_()) 
单击开始按钮和停止按钮后,集成将自动停止 我得到这个输出:

>>preparing Integration
>>Integration too long - User terminated
>>Integral(sqrt((3*t + 1)/t), t)
>>finished...
这不完全是我的问题,但我想了解如何使用线程来放置 耗时的计算并停止它们,以便尝试其他参数或初始猜测 当使用类似 甚至可以从外部停止迭代函数并重新启动它而不进入无响应状态吗? 任何有助于改进的都将不胜感激。 我在这里举了这些例子作为指导
并且

您应该设计线程工作负载,以便将其分割为多个循环,而不是以同步和阻塞的方式执行,这样您就可以在尝试每个循环之前检查工作线程是否收到停止消息,如果是,则以安全的方式终止工作负载。否则你只能以丑陋的方式结束。这将涉及使用worker对象的成员而不是本地成员来跟踪工作负载的状态和进度,以便这些成员可以在工作负载循环中保持不变。但是如果任务不能被分割成循环?有解决方法吗?@Hiatus将任务分割成循环是首选方法,即使使用scipy.optimize.minimize,您也可以指定maxIter。您也可以使用上一次最小化的输出作为下一轮的开始来重新启动。但是杀死仍然运行terminate的QThread确实是个坏主意,因为您不知道会导致什么副作用。不要那样做。查看终止的原因和方法right@Trilarion当使用Scipy最小化时,我无法作为循环访问迭代,因为我无法使用从Symphy导入的集成。我想导入一个模块,并能够停止线程内的任何交互进程