2

Rhythmbox プラグインを作成し、JSON を非同期でダウンロードするコードを追加しようとしています。コールバックはdo_activate関数に登録されます:

def do_activate(self):
    shell = self.object
    sp = shell.props.shell_player
    self.db = shell.get_property('db')
    self.qm = RB.RhythmDBQueryModel.new_empty(self.db)
    self.pec_id = sp.connect('playing-song-changed', self.playing_entry_changed)
    self.pc_id = sp.connect('playing-changed', self.playing_changed)
    self.sc_id = sp.connect('playing-source-changed', self.source_changed)
    self.current_entry = None

    ...

playing_changedがトリガーされたときにコンテンツをダウンロードしようとしています。現在urllib2、コンテンツを同期的にダウンロードするために使用されていますが、これにより、UI がしばらくブロックされる可能性があります。問題を解決するために Twisted を使用したいのですが、私が見たすべての例ではreactor.run()、無期限にブロックする を使用しています。

私は Twisted にかなり慣れていないので、メイン スレッドをブロックせずにこのケースを非同期で処理する方法はあるのでしょうか?

完全なコードはこちら

4

2 に答える 2

2

IO ループ ( ) を実行せずに非同期 http 要求を実行する方法はツイストにはありませんreactor.run。実行reactorすると、デフォルトでは Python に存在しない非同期機能を使用できます。ただし、twisted を使用する唯一の理由が非同期の http 呼び出しを行うことである場合、それはやり過ぎかもしれません。代わりに単純なスレッドを使用し、スレッドに http 応答を待機させます。

于 2012-10-18T11:25:53.190 に答える
2

Rhythmbox プラグインのコンテキストでは、おそらく GTK メイン ループが既に実行されているという事実に対処する必要があります。これは Twisted が原則としてサポートする状況ですが、サポートされている API がメイン ループ上でリアクターを協調的に初期化するのは難しいものです。

次のような関数で回避できます。

def maybeInstallReactor():
    import sys
    if 'twisted.internet.reactor' not in sys:
        from twisted.internet import gtk2reactor # s/2/3 if you're using gtk3
        reactor = gtk2reactor.install()
        reactor.startRunning()
        reactor._simulate()
    else:
        from twisted.internet import reactor
    return reactor

この関数は、他のもの (特に Twisted からのもの) がインポートされる前に、プログラムのできるだけ早い段階で呼び出されるようにしてください。

呼び出しはstartRunningリアクターを GLib メイン ループに接続し、_simulate呼び出しは Twisted の時間イベントを GLib タイマーに接続します。

悲しいことに、これには 1 つのプライベート関数を呼び出す_simulate必要があるため、Twisted の新しいバージョンがそれを壊さないように注意する必要があります。しかし、この質問の結果として、このユースケースを明示的にサポートするためにバグをオープンしました。 さらに、この 1 つのプライベート メソッド呼び出しを除けば、Twisted の使用法について奇妙である必要はありません。

于 2012-10-19T06:40:02.227 に答える