[英]Execute async callback from synchronous code immediately
Problem 问题
I have a library which currently has no async support and needs to be called from async code. 我有一个目前不支持异步的库,需要从异步代码中调用。 The async code calls into the library through a handler (
handler
function in the code below). 异步代码通过处理程序(下面的代码中的处理
handler
函数)调用库。 While the handler executed, the library periodically calls a callback ( callback_wrapper
) to report progress. 在执行处理程序时,库会定期调用回调(
callback_wrapper
)以报告进度。
The synchronous handler is executed in a ThreadPoolExecutor
in order for the main event loop to be able to process further events while the handler is running. 同步处理程序在
ThreadPoolExecutor
中执行,以便主事件循环能够在处理程序运行时处理其他事件。
What happens is that the synchronous callback is executed immediately, but the async callback is only executed after the main handler has executed. 发生的情况是立即执行同步回调,但是异步回调仅在主处理程序执行后执行。 The desired result is the async callbacks to be executed immediately.
理想的结果是立即执行异步回调。
I guess the event loop is blocked at the run_in_executor
call, but I am not sure how to resolve this. 我猜想事件循环在
run_in_executor
调用中被阻止,但是我不确定如何解决这个问题。
Code 码
import asyncio
import time
from concurrent.futures.thread import ThreadPoolExecutor
loop = asyncio.get_event_loop()
def handler():
print('handler started')
callback_wrapper()
time.sleep(1)
print('handler stopped')
async def callback():
print('callback')
def callback_wrapper():
print('callback wrapper started')
asyncio.ensure_future(callback(), loop=loop)
print('callback wrapper stopped')
async def main():
handler()
with ThreadPoolExecutor() as pool:
async def thread_handler():
await loop.run_in_executor(pool, handler)
loop.run_until_complete(main())
Output 输出量
handler started
callback wrapper started
callback wrapper stopped
handler stopped
callback
Desired Output 期望的输出
handler started
callback wrapper started
callback
callback wrapper stopped
handler stopped
thanks to @user4815162342's input, I came up the the following solution: 感谢@ user4815162342的输入,我提出了以下解决方案:
import asyncio
import time
from concurrent.futures.thread import ThreadPoolExecutor
loop = asyncio.get_event_loop()
def handler():
print('handler started')
callback_wrapper()
time.sleep(1)
print('handler stopped')
async def callback():
print('callback')
def callback_wrapper():
print('callback wrapper started')
asyncio.run_coroutine_threadsafe(callback(), loop).result()
print('callback wrapper stopped')
async def main():
await thread_handler()
with ThreadPoolExecutor() as pool:
async def thread_handler():
await loop.run_in_executor(pool, handler)
loop.run_until_complete(main())
which produces the desired result: 产生预期的结果:
handler started
callback wrapper started
callback
callback wrapper stopped
handler stopped
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.