6

ツイストを使用してコードをより非同期にする方法を見つけようとしています。

  • 関数は遅延オブジェクトを返します
  • 次に、コールバックのリストを追加します
  • 最初のコールバックは、遅延関数が次のような結果を提供した後に呼び出されます。deferred_obj.callback
  • 次に、コールバックのチェーンで、最初のコールバックがデータを処理し、2番目のコールバックを呼び出します
  • や。。など。

ただし、チェーンされたコールバックはチェーンされているため非同期とは見なされず、イベントループは、それ以上なくなるまで、それぞれを同時に起動し続けます。

ただし、遅延オブジェクトがあり、そのコールバックとしてdeferred_obj.callbackをアタッチした場合d.addCallback(deferred_obj.callback)、deferred_objはデータを待機しているため、これは非同期と見なされ、データを渡すメソッドはデータを待機しています。同様に、ただし、i d.callback'd'オブジェクトがデータを処理すると、deferred_obj.callbackが呼び出されます。ただし、このオブジェクトは遅延されるため、連鎖コールバックの場合とは異なり、非同期で実行されます...正しいですか?

私のコードがすべて非ブロッキングであると仮定すると、これは、連鎖コールバックが非同期ではないのに対し、連鎖遅延は非同期ではないことを意味しますか?

4

4 に答える 4

8

コールバックは(デフォルトで)同期しています。ただし、Twisted docが指摘しているように、次のようになります。

あるDeferredを別のDeferredで待機する必要がある場合は、addCallbacksに追加されたメソッドからDeferredを返すだけです。

したがって、これを使用して、コールバックチェーンで非同期処理を行うことができます。そうしよう:

from twisted.internet import reactor, defer

def callback_func_2(result, previous_data):
    # here we pass the result of the deferred down the callback chain
    # (done synchronously)
    print "calling function 1 on result:%s with previous result:%s" % (result, previous_data)
    return result

def callback_func(result):
    #let's do some asynchronous stuff in this callback
    # simple trick here is to return a deferred from a callback 
    # instead of the result itself.
    # 
    # so we can do asynchronous stuff here, 
    # like firing something 1 second later and have 
    # another method processing the result
    print "calling function 1 on result:%s" % result
    d = defer.Deferred()
    reactor.callLater(1, d.callback, "second callback")
    d.addCallback(callback_func_2, result)
    return d

def do():
    d = defer.Deferred()
    reactor.callLater(1, d.callback, "first callback")
    d.addCallback(callback_func)
    return d

do()
reactor.run()
于 2010-12-29T09:54:13.200 に答える
2

ある種ですが、このタイプのイベント処理には同時実行性はありません。コードがイベントループに戻るまで、新しいコールバックは呼び出されません。したがって、コールバックのチェーンは同期しています。イベントループでは非同期のみです。

これは、このタイプのプログラミングの1つの注意点であり、ハンドラーは最も迅速に実行され、できるだけ早くイベントループに戻ります。ハンドラーで時間のかかるタスクを実行するべきではありません。

于 2010-12-27T21:22:19.610 に答える
0

延期を使用しても、コードは非同期になりません。

import time
from twisted.internet import defer
from twisted.internet import reactor

def blocking(duration, deferred):
    print "start blocking"
    time.sleep(duration)
    print "finished blocking"
    deferred.callback(True)

def other_task():
    print "working..."
    reactor.callLater(1, other_task)

def finish(result):
    print "stopping reactor in 2sec"
    reactor.callLater(2, reactor.stop)

def failed(reason):
    print reason
    print "stopping reactor in 2sec"
    reactor.callLater(2, reactor.stop)

def main():
    d = defer.Deferred()
    d.addCallbacks(finish, failed)
    reactor.callLater(0, blocking, 5, d)

if __name__ == "__main__":
    reactor.callLater(0, other_task)
    main()
    reactor.run()

実行時間の長い同期コードがある場合は、Cooperator(twisted.internet.task)を使用して、deferToThreadを実行するか、短い反復に分割することができます。

于 2010-12-27T22:40:06.207 に答える
0

クリーンなアプローチでコードをより非同期にしたい場合は、次のフレームワークを確認してください。

https://github.com/iogf/untwisted

明確なドキュメントを備えたきちんとしたコードがあります。非同期モデルを処理するためのアプローチは簡単です。

于 2016-04-06T07:29:27.610 に答える