这就是我想要完成的。我正在远程调用服务器以获取信息,我想阻止以等待信息。我创建了一个返回 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 块中,但如果这是唯一的方法,我总是可以诉诸于此。

有帮助吗?

解决方案

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

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

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

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top