Multithreading PyQt:如果进程运行太长,如何使用Qthread使其可停止
我读了很多关于线程的文章,但我真的需要这方面的帮助: 我有一个PyQt主GUI,它使用scipy运行优化。最小化。。。 因为我不能举例说明,所以我使用了占位符过程 来说明我的问题是什么 我想让主GUI保持可由用户停止,如果这个过程需要太长时间 结果。 我的工作示例是这样一个,其中我使用了与Symphy的集成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
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导入的集成。我想导入一个模块,并能够停止线程内的任何交互进程