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
相關文章
相關標籤/搜索