2016-10-31 1 views
3

this質問をする必要があります。コールバックと同期待ちの束なしで、別のスレッドからasyncioコルーチンをスケジューリングする

メッセージを送信するコルーチンsendがあります。私は(スレッド2で実行されている)loop2から(スレッド1で実行されている)loop1でそれをスケジュールする:

async def send_threadsafe(self, message, current_loop=loop2, dest_loop=loop1): 
    future = asyncio.run_coroutine_threadsafe(
     send(message), loop=dest_loop 
    ) 

asyncio.run_coroutine_threadsafeによって返さfutureconcurrent.futures.Futureで、非同期的に待っていたことができません。

質問:私はどのようにしてfutureを適切に待っていますか、または待ち受けできるオブジェクトを取得するためにsendをどのようにスケジュールする必要がありますか?

私は私が行うことができます知っている:

async def send_threadsafe(...): 
    future = ... 
    result = await current_loop.run_in_executor(None, future.result) 

しかし、別のスレッドを使用せずにそれを行う方法はありますか? run_in_executorfuture.resultをスレッドプールに送信するので、私はそのスレッドプールを利用したくありません。

私がcall_soon_threadsafeを使用したくない理由は、いくつかのコールバックを作成する必要があるからです。まず、sendの実行をloop1にスケジュールする。次にsendloop1に実行し、3番目のコールバックをloop2にスケジュールします。第3に、asyncio futureがスレッドセーフではなく、結果をloop1に設定できないため、最初のコールバックで作成された未来に結果を設定することです。

答えて

3

あなたが同時未来からasyncio未来を取得するためにasyncio.wrap_futureを使用することができます。

from concurrent.futures import Executor 

class AsyncioExecutor(Executor): 

    def __init__(self, loop): 
     self.loop = loop 

    def submit(self, fn, *args, **kwargs): 
     coro = fn(*args, **kwargs) 
     return asyncio.run_coroutine_threadsafe(coro, self.loop) 

例:

async def send_threadsafe(self, message, destination, *, loop=loop): 
    concurrent = asyncio.run_coroutine_threadsafe(
     send(message), loop=destination) 
    return await asyncio.wrap_future(concurrent, loop=loop) 

asyncio executorを実装することによって、同じことを達成することが可能です

executor = AsyncioExecutor(remote_loop) 
result = await loop.run_in_executor(executor, send, message) 
+0

ありがとう、これは私が探していたものです!ちなみに、最初の例では、 'def send_threadsafe()'は 'def send_threadsafe()'であるべきではありませんか? – Zelta

+0

@ZeltaOops、修正されました! – Vincent

関連する問題