在不同线程

时间:2017-04-21 19:40:28

标签: python multithreading python-3.x thread-safety python-asyncio

我有一个库,可以让我选择在外部作业完成时安排回调。对Future.set_result()使用此回调是否安全?如果没有,实现这一目标的正确方法是什么? 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()

2 个答案:

答案 0 :(得分:3)

在仔细阅读文档之后,似乎应该在事件循环调度的回调中设置未来的值:

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

答案 1 :(得分:1)

另一个选择是使用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)

或者由于该函数是异步def,你甚至可以在循环中等待它,用

替换最后一行
    await asyncio.futures.wrap_future(fut, loop = loop)