2012-03-07 48 views
4

我遇到以下代碼的問題。在我的真實情況下,由SomeClass封裝的邏輯具有阻塞邏輯,所以我需要用reactor.callFromThread()來調用它。當我發出sigint信號時,我想讓SomeClass.run()中的循環停止,我的理解是,在addSystemEvent鉤子中放置一些代碼來處理這個問題。我認爲這對我對Python和線程的理解可能更多的問題,而不是Twisted本身。如何中斷Twisted中的線程?

from twisted.internet import reactor 
import time 

class SomeClass(): 
    def __init__(self): 
     self.running = False 

    def run(self): 
     self.running = True 
     while(self.running): 
      print('foo') 
      time.sleep(5) 

    def stop(self): 
     print('stopping') 
     self.running = False 

someClassInstance = SomeClass() 

def cleanup(): 
    someClassInstance.stop() 

reactor.addSystemEventTrigger('before', 'shutdown', cleanup) 
reactor.callFromThread(someClassInstance.run) 
reactor.run() 

回答

4

不可能安全地和一般地中斷Python等編程語言中的線程。 Java曾經有過這個功能,但是they removed it因爲它本質上是不安全的。 (Java中有一項新功能,Thread.interrupt,這是一個限制版,問題較少,但它仍然使編寫多線程代碼的任務複雜化)。

這就是爲什麼Twisted提供了很多方法來避免線程。如果你不需要它們,請不要使用它們。例如,不要致電time.sleep(n); foo()只需執行reactor.callLater(n, foo),您將得到相同的效果,但callLater返回可用於輕鬆取消或推遲foo的執行(如果尚未發生)的對象。

如果您有什麼你實際上試圖做的,而不是「再有事」代以「time.sleep」的一個例子,請打開另一個問題闡述就可以了。答案真的取決於你在做什麼 - 你是否真的在等待時間?阻止I/O到另一個進程?另一臺機器?扭曲有適合所有這些設施。

+0

本質上,我正在阻止網絡調用:調用一些遺留庫來完成同步IMAP客戶端工作。目前我至少通過使用'callInThread()'而不是'callFromThread()'來工作,但我很想知道如何以更正確的扭曲方式對我的阻止代碼進行沙箱處理。編輯:我只是意識到我可以用'deferToThread()',這看起來更好,但我仍然使用線程! – Cera 2012-03-07 06:20:13