在来自不同线程的回调中设置asyncio.Future的值
问题描述:
我有一个库,它提供了一个选项,可以在外部作业完成时安排回调。 Future.set_result()
使用此回调安全吗?如果没有,那么实现这一目标的正确方法是什么?未来的文档说它的方法不是线程安全的,所以我认为这可能有问题。在来自不同线程的回调中设置asyncio.Future的值
我的目标是使用PyOpenCL中的OpenCL事件作为asyncio代码中的等待对象。我在想一个辅助函数是这样的:
def wrap_opencl_event(event):
f = asyncio.Future()
event.set_callback(pyopencl.command_execution_status.COMPLETE, lambda x: f.set_result(None))
return f
,并用它这种方式:
async def do_slow_stuff():
ev1 = pyopencl.enqueue_something()
ev2 = pyopencl.enqueue_something_else(wait_for=[ev1])
await wrap_opencl_event(ev2)
process_results()
答
读一点更彻底看来,未来的价值应该在回调中设置的文件后计划与事件循环:
def wrap_opencl_event(event):
loop = asyncio.get_event_loop()
f = loop.create_future()
event.set_callback(pyopencl.command_execution_status.COMPLETE,
lambda status: loop.call_soon_threadsafe(f.set_result, None))
return f
答
另一种选择是使用concurrent.futures和包裹未来
import asyncio.futures, concurrent.futures
async def func_returning_future(loop):
fut = concurrent.futures.Future()
# Pass off to your other thread somehow
# and return a wrapped future for asyncio
return asyncio.futures.wrap_future(fut, loop = loop)
或者因为函数是一个异步高清你甚至可以在循环中等待它,与
await asyncio.futures.wrap_future(fut, loop = loop)
替换最后一行