2

これが私が達成しようとしていることです。情報を得るためにサーバーにリモート呼び出しを行っていますが、情報を待つためにブロックしたいと思います。RPCが応答を受け取ると、遅延が呼び出されるように、遅延を返す関数を作成しました。次に、行くスレッドから呼び出される関数があります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

これは正常に機能します。サーバーがダウンすると、接続が失われ、エラーバックがトリガーされます。ただし、サーバーがダウンせず、すべてが正常にシャットダウンした場合onConnectionLostでも、起動され、ここでの匿名コールバックはerrbackをトリガーしようとし、AlreadyCalled例外が発生します。

延期されたものがすでに解雇されていることを確認するためのきちんとした方法はありますか?ブロックで包むのは避けたいのですがtry/except、それが唯一の方法であれば、いつでもそれに頼ることができます。

4

1 に答える 1

5

方法はありますが、絶対にやってはいけません。を起動しているコードは、関連付けられた状態でDeferred起動されたかどうかを追跡する必要があります。Deferred実際には、 を起動するときはDeferred、適切にガベージ コレクションを実行できるように、それを見失う必要があります。そうすれば、参照がなくなるため、2 回呼び出すことを心配する必要はありません。

また、呼び出しdeferredfuncているのと同じスレッドから呼び出しているようですblockingCallFromThread。そうしないでください。を返す関数Deferredsは、リアクタ API を呼び出している可能性が高く、これらの API はスレッド セーフではありません。実際、Deferredそれ自体はスレッドセーフではありません。これがではなくである理由です。あなたがすべきです。blockingCallFromThreadblockOnThisDeferredFromThreadblockingCallFromThread(reactor, deferredfunc, args)

本当に errback-if-been-call-otherwise-do-nothing 動作が必要な場合は、Deferredをキャンセルすることをお勧めします。

于 2010-07-26T17:26:24.700 に答える