在来自不同线程的回调中设置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) 
替换最后一行