asyncio 中给running 的loop 动态添加 Future Task

https://my.oschina.net/backbye/blog/1919486python

 

asyncio 提供了两个给运行中的事件循环(loop) 添加 事件的方法安全

call_soon_threadsafe() 、run_coroutine_threadsafe()async

由于咱们通常的场景中会另起一个线程来启动loop( loop.run_forever() ),因此上面两个方法设计成线程安全oop

可是上面两个方法并不能知足咱们所有的须要:.net

1. run_coroutine_threadsafe 只能用于传入一个协程,而不能直接传入task对象(这样才方便咱们在主进程中随时查看任务的执行状况和获取结果),固然能够去修改源码,可是不建议这么作线程

2. run_forever 虽然解决了能够随时加入任务的问题,可是带来一个新的问题:这个线程会一直运行下去,除非ctrl-C, 由于1,因此咱们没法根据任务的执行状况来loop.stop, 并且因为线程安全,即便你执行了loop.stop() 也不会起任何做用设计

因此源头要回到线程安全上去解决,查看源码发现是经过一个管道文件来实现的,能够理解为内置了一个队列,一切对loop的修改都要经过发送一个信号到这个队列,才能同步到running loop的那个线程中,从而产生效果。协程

发送信号代码:loop._csock.send(b'\0')对象

下面给个示例,本身去体会blog

 

import asyncio
import threading

def start_loop(loop):
    asyncio.set_event_loop(loop)
    loop.run_forever()
    print(asyncio.Task.all_tasks().pop().result())
    
    
async def do_some_work(name):
    for i in range(5):
        print(f"{name}: is working")
        await asyncio.sleep(1)
    return True
        
loop = asyncio.new_event_loop()

threading.Thread(target=start_loop, args=(loop,)).start()

task = loop.create_task(do_some_work("Lili"))

loop._csock.send(b'\0')

while True:
    if task.done():
        loop.stop()
        loop._csock.send(b'\0')
        break
相关文章
相关标签/搜索