2

这就是我想要完成的。我正在远程调用服务器以获取信息,我想阻止以等待信息。我创建了一个返回 Deferred 的函数,这样当 RPC 带有回复时,就会调用 deferred。然后我有一个从线程调用的函数threads.blockingCallFromThread(reactor, deferredfunc, args)

如果出现问题——例如,服务器宕机——那么呼叫将永远不会解除阻塞。在这些情况下,我更希望延迟的人例外。

我部分成功了。我有一个延迟,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,从而引发AlreadyCalled异常。

有没有什么巧妙的方法来检查一个 deferred 是否已经被解雇了?我想避免将它包装在一个try/except块中,但如果这是唯一的方法,我总是可以诉诸于此。

4

1 回答 1

5

有办法,但你真的不应该这样做。您正在触发的代码Deferred应该跟踪它是否Deferred在关联状态下被触发。真的,当你触发 时Deferred,你应该忘记它,以便它可以被正确地收集垃圾;这样你就不必担心调用它两次,因为你不会再引用它了。

此外,看起来您是从您正在调用deferredfunc的同一个线程中调用的blockingCallFromThread。不要那样做;返回的函数Deferreds最有可能调用反应器 API,而这些 API不是线程安全的。事实上,Deferred它本身并不是线程安全的。这就是为什么它是,不是。你应该这样做。blockingCallFromThreadblockOnThisDeferredFromThreadblockingCallFromThread(reactor, deferredfunc, args)

如果您真的想要 errback-if-it's-been-called-otherwise-do-nothing 行为,您可能需要取消Deferred。

于 2010-07-26T17:26:24.700 回答