我開始Qthread在我的 GUI 中執行優化功能。我想包括一個可以中斷的停止功能Qthread,并立即結束優化功能。
我讀到Qthread.terminate()不推薦使用;使用停止標志是不可能的,因為函式的性質不是回圈。
我想過QTimer在QThread(一個看門狗定時器)中使用一個定期檢查一個停止標志,如果它被觸發,就結束優化功能,但我真的無法想象這樣的想法是如何寫出來的。
有任何想法嗎?
class Worker(QObject):
finished = pyqtSignal()
def run(self):
# implement a QTimer here that will somehow interrupt the minimize function
# minimize is an arbitrary function that takes too long to run, and uses child processes to do so
result = minimize(something)
FROM_Optimization_Process,_ = loadUiType(os.path.join(os.path.dirname(__file__),"ui_files/Optimization_process_window.ui"))
class Optimization_process_window(QDialog, FROM_Optimization_Process):
def __init__(self, parent=None):
# first UI
super(Optimization_process_window, self).__init__(parent)
self.setupUi(self)
def start_solving_thread(self):
self.thread = QThread()
self.thread.daemon = True
self.worker = Worker()
self.worker.moveToThread(self.thread)
self.thread.started.connect(self.worker.run)
self.worker.finished.connect(self.thread.quit)
self.worker.finished.connect(self.worker.deleteLater)
self.thread.finished.connect(self.thread.deleteLater)
self.thread.start()
def stop_solving(self):
# implement an interrupt function here
self.thread.quit()
self.thread.wait()
uj5u.com熱心網友回復:
您誤解了計時器的作業原理。它們不能以任何方式“中斷”在執行緒中運行的代碼。只有當執行緒中的事件回圈空閑并準備好處理定時器事件和信號時,定時器才能作業。如果該執行緒中正在運行某些代碼,則該事件回圈將被阻止。
換句話說,QTimer在你的執行緒中不會作業,除非你不時地解除阻塞事件回圈來處理定時器信號。但據我所見,您可能在您的minimize(something)功能中做了一些密集的作業。它完全阻止了事件回圈。
如果您希望能夠實作作業者/執行緒中斷,唯一的方法是minimize(something)通過定期輪詢在您的函式中實作中斷。您需要將此函式中的作業拆分為某些塊,并在每個塊完成后,檢查是否應該停止作業/執行緒。
QThread有一個幫助函式。它是QThread.requestInterruption()和QThread.isInterruptionRequested(),這些函式是執行緒安全的。您可以通過呼叫從您的作業人員訪問執行緒實體QObject.thread()。但是你有責任QThread.isInterruptionRequested()在每個作業塊完成后對代碼進行足夠頻繁的檢查。
當然,您可以開發自己的方法來中止作業,可能由互斥鎖保護......但是您必須定期檢查它。沒有其他辦法了。
def minimize(self, something): # a method of Worker class
for i in range(1000000):
if i % 1000 == 0: # this is just to represent a block of work
if self.thread().isInterruptionRequested():
return
self.minimize_next_part(something)
self.finished.emit()
那么停止函式應該是:
def stop_solving(self):
self.thread.requestInterruption() # this will unblock the event loop in just a moment
self.thread.quit() # this ends event loop and will emit thread's finished signal
# self.thread.wait() # you do not need this probbaly, it depends...
(對于潛在的語法錯誤,我很抱歉,我是 C 程式員,而不是 Pythonista)
我知道這看起來很愚蠢,但實際上沒有其他神奇的機制可以中斷執行緒。您只需要定期輪詢。
PS:代替
self.worker.finished.connect(self.worker.deleteLater)
你應該使用
self.thread.finished.connect(self.worker.deleteLater)
否則,如果執行緒被中斷,則不會洗掉作業人員,因為Worker.finished信號永遠不會被呼叫。
轉載請註明出處,本文鏈接:https://www.uj5u.com/shujuku/429973.html
