从另一个线程调度asyncio协同程序

kfx*_*kfx 5 python multithreading python-3.x python-asyncio

我尝试使用另一个线程安排asyncio协同程序create_task().问题是没有调用协程,至少在合理的时间内没有.

是否有办法唤醒事件循环或至少指定更短的超时?

#!/usr/bin/python3

import asyncio, threading

event_loop = None

@asyncio.coroutine
def coroutine():
    print("coroutine called")

def scheduler():
    print("scheduling...")
    event_loop.create_task(coroutine())
    threading.Timer(2, scheduler).start()

def main():
    global event_loop

    threading.Timer(2, scheduler).start()

    event_loop = asyncio.new_event_loop()
    asyncio.set_event_loop(event_loop)
    event_loop.run_forever()

main()
Run Code Online (Sandbox Code Playgroud)

输出:

scheduling...
scheduling...
scheduling...
scheduling...
Run Code Online (Sandbox Code Playgroud)

kfx*_*kfx 9

根据Task的文档"这个类不是线程安全的".因此,预计从另一个线程调度不会起作用.

我根据这里的答案和评论找到了两个解决方案.

  1. @ wind85回答:直接用create_task呼叫替换线路asyncio.run_coroutine_threadsafe(coroutine(), event_loop)呼叫.需要Python 3.5.1.

  2. 使用call_soon_threadsafe安排一个回调,然后创建任务:

    def do_create_task():
        eventLoop.create_task(coroutine())
    
    def scheduler():
        eventLoop.call_soon_threadsafe(do_create_task)
    
    Run Code Online (Sandbox Code Playgroud)