首页 > 解决方案 > Python:带线程的异步循环

问题描述

你能告诉我这是否是在自己的线程中构建多个独立异步循环的正确方法吗?

def init():
    print("Initializing Async...")
    global loop_heavy
    loop_heavy = asyncio.new_event_loop()
    start_loop(loop_heavy)

def start_loop(loop):
    thread = threading.Thread(target=loop.run_forever)
    thread.start()

def submit_heavy(task):
    future = asyncio.run_coroutine_threadsafe(task, loop_heavy)
    try:
        future.result()
    except Exception as e:
        print(e)

def stop():
    loop_heavy.call_soon_threadsafe(loop_heavy.stop)

async def heavy():
    print("3. heavy start %s" % threading.current_thread().name)
    await asyncio.sleep(3) # or await asyncio.sleep(3, loop=loop_heavy)
    print("4. heavy done")

然后我正在测试它:

if __name__ == "__main__":
    init()
    print("1. submit heavy: %s" % threading.current_thread().name)
    submit_heavy(heavy())
    print("2. submit is done")
    stop()

我期待看到1->3->2->4,但实际上它是1->3->4->2

Initializing Async...
1. submit heavy: MainThread
3. heavy start Thread-1
4. heavy done
2. submit is done

我认为我在理解异步和线程方面错过了一些东西。
线程不同。为什么我要在里面MainThread等到里面的工作Thread-1完成?

标签: python-3.xpython-asynciopython-multithreading

解决方案


为什么我要在里面MainThread等到里面的工作Thread-1完成?

好问题,你为什么?

一个可能的答案是,因为您实际上阻塞当前线程,直到作业完成。这是将事件循环放在另一个线程中并使用run_coroutine_threadsafe.

另一个可能的答案是,如果您不想要,则不必这样做。您可以简单地从返回submit_heavy()concurrent.futures.Future对象返回run_coroutine_threadsafe,然后让调用者自己等待结果(或检查是否准备好)。

最后,如果您的目标只是“在后台”运行常规函数(不阻塞当前线程),那么您可能根本不需要 asyncio。看看这个concurrent.futures模块,它ThreadPoolExecutor允许您轻松地将函数提交到线程池并让它在无人协助的情况下执行。


推荐阅读