2017-05-27 69 views
1

我試圖爲包裝長時間運行的函數的GUI創建線程。我的問題因此用PyQt和QThreads來表示,但我想象的是同樣的概念也可以適用於標準的python線程,並且一般會感謝任何建議。終止包裝函數的QThread(即不能輪詢「wants_to_end」標誌)

通常情況下,允許一個線程退出運行時,據我所知,包括定期在線程內查了「wants_to_end」標誌是一個很好的做法 - 比如:

Pseudocode (in my thread): 
def run(self): 
    i = 0 
    while (not self.wants_to_end) and (i < 100): 
     function_step(i) # where this is some long-running function that includes many streps 
     i += 1 

然而,正如我GUI是包裝一個預先編寫的長時間運行的函數,我不能簡單地在長時間運行的代碼中插入這樣的「wants_to_end」標記輪詢。

是否有另一種方法強制終止我的工作線程從我的主GUI(即使我包括一個按鈕在GUI中停止處理)?

我簡單的例子的情況是:

class Worker(QObject): 
    finished = pyqtSignal() 

    def __init__(self, parent=None, **kwargs): 
     super().__init__(parent) 
     self.kwargs = kwargs 


    @pyqtSlot() 
    def run(self): 
     result = SomeLongComplicatedProcess(**self.kwargs) 
     self.finished.emit(result) 

與我的主窗口界面中使用:

self.thread = QThread() 
    self.worker = Worker(arg_a=1, arg_b=2) 
    self.worker.finished.connect(self.doSomethingInGUI) 
    self.worker.moveToThread(self.thread) 
    self.thread.started.connect(self.worker.run) 
    self.thread.start() 

回答

1

如果長時間運行的功能塊,強制停止線程是通過它的唯一的出路terminate()方法(也可能需要撥打wait())。但是,也不能保證,這將總是工作,和文檔也說明如下:

警告:此功能是危險的,不鼓勵使用。 線程可以在其代碼路徑中的任意點終止。線程可以在修改數據時終止 。線程沒有機會自己清理後,解鎖任何持有的互斥體等。總之,只有在絕對必要時才使用 這個函數。

更清潔的解決方案是使用一個單獨的過程,而不是一個單獨的線程。在Python中,這可能意味着使用multiprocessing模塊。但是,如果您不熟悉這一點,可以通過QProcess(它提供的信號應該允許更容易與GUI集成)作爲腳本運行該函數可能會更簡單。您可以隨時根據需要簡單地kill()工作進程。但是,如果該解決方案在某種程度上不令人滿意,還有許多其他IPC approaches可能更適合您的要求。

+0

感謝您的回覆。我試過.terminate(),但線程剛剛運行!這聽起來像多處理是一個很好的路線。我現在要學習文檔,但如果你有一個最低工作範例,那也會很棒!謝謝。 – PhysLQ

+1

@PhysLQ。看一個簡單的例子[這個答案](https://stackoverflow.com/a/40093862/984421)。 – ekhumoro

+0

謝謝。你認爲在這裏使用多處理或QThread更好嗎?我對這兩者都有一定的瞭解,但是會對它們進行研究。 – PhysLQ