2010-07-26 69 views
1

這是我正在努力完成的。我正在遠程調用服務器以獲取信息,並且我想阻止等待信息。我創建了一個返回Deferred的函數,這樣當RPC進入回覆時,調用deferred。然後我有一個從threads.blockingCallFromThread(reactor, deferredfunc, args)線程調用的函數。twisted:檢查延期是否已被調用

如果出現問題 - 例如服務器故障 - 那麼呼叫將永不解除。在這些情況下,我寧願推遲推遲以排除異常。

我部分成功。我有一個推遲的,onConnectionLost,當連接丟失時會關閉。我修改我的阻止呼叫功能爲:

deferred = deferredfunc(args) 
    self.onConnectionLost.addCallback(lambda _: deferred.errback(
     failure.Failure(Exception("connection lost while getting run")))) 
    result = threads.blockingCallFromThread(
     reactor, lambda _: deferred, None) 
    return result 

這工作正常。如果服務器關閉,則連接丟失,並觸發errback。但是,如果服務器沒有關閉並且所有東西都乾淨地關閉,則onConnectionLost仍然會被觸發,並且匿名回調會嘗試觸發errback,從而導致發生異常。

是否有任何干淨的方式來檢查延期已被解僱?我想避免將它封裝在try/except區塊中,但如果這是唯一的方法,我總是可以訴諸於此。

回答

4

有辦法,但你真的不應該這樣做。您正在觸發Deferred的代碼應該跟蹤是否觸發了Deferred或不在關聯狀態。真的,當你開火Deferred時,你應該忽略它,以便它可以正確地收集垃圾;這樣你永遠不用擔心兩次調用它,因爲你不會再有任何參考。

此外,它看起來像你打電話deferredfunc從你打電話blockingCallFromThread相同的線程。不要那樣做;返回Deferreds的函數很可能調用反應堆API,並且這些API是非線程安全。實際上,Deferred本身並不是線程安全的。這就是爲什麼它是blockingCallFromThread而不是blockOnThisDeferredFromThread。你應該做blockingCallFromThread(reactor, deferredfunc, args)

如果你真的想要errback-if-it-been-called-otherwise-otherwise-do-nothing行爲,你可能需要cancel Deferred。

+0

所以我如何取消延期如果我沒有訪問它,因爲我必須調用'blockingCallFromThread'是線程安全的?是修改該函數以執行'onConnectionLost.addCallback(lambda _:d.cancel())'的唯一方法,其中'd'是延遲它將要返回?這意味着不得不通過它onconnectionlost推遲 – Claudiu 2010-07-26 17:34:55

+1

你可以調用'blockingCallFromThread(self.something)',其中'self.something'持有'延遲'給你。問題在於從錯誤的線程調用反應器API,而不是從錯誤的對象調用。 – Glyph 2010-07-26 17:41:28

+0

是的,我最終這樣做。然而,我無法取消工作,但似乎沒有任何效果。我只是做了一個幫助函數,它需要延遲並嘗試觸發errback。有沒有細節我不知道的'.cancel'?從文檔看來,如果我什麼都不做特別的話,'.cancel'應該會觸發一個CancelledError errback(如果它沒有被調用),否則什麼也不做。 – Claudiu 2010-07-26 19:04:38