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