最重要的是生成器函數碰到yield停止執行,收到next或send才會繼續執行的機制。
而且send方法令我們可以傳遞值到生成器暫停的地方。
生成器執行結束拋出 StopIteration 異常。
yield from用於把其他生成器當做子例程調用。
然後它可以被其他用 async def 定義的的協程函數B和C await ,只有當 await 返回時,B和C才繼續執行。
這樣我們就可以有效地控制B和C的執行順序。
然後我們創建了壹個調度器,它對列表進行了兩次深拷貝以避免問題。它循環協程隊列,使用 send 方法對每個協程依次遞進,如果有協程已經完成則將其移出隊列,當列表中的協程全部完成時結束。
然後通過 args=coro.send(None) 與該函數碰撞,得到含有 delay 參數的字典作為 send 的返回值。便可以判斷出是否調用調度器的睡眠機制。
最後在調度器中實現每壹次協程列表循環結束後判斷在睡眠列表中的協程是否有到時間的,到時間或時間超出則添加到運行協程列表中進入循環執行。如果運行列表中的協程都執行完了,則查看睡眠列表中的協程中還需睡眠的最少時間,線程睡眠,睡眠完成再將其添加到運行隊列。
該裝飾器能將壹個比較耗時的計算函數封裝為壹個協程,使其可以被其他協程 await 。在調度器中利用 send 函數的返回值可以獲取它的類型為 background 、函數入口地址以及函數的傳參,然後在調度器中按相應機制執行。
第二部分 是在調度器中的修改:我們讓調度器類擁有了壹個私有的 concurrent.futures.ThreadPoolExecutor() 對象。並在運行協程隊列的循環判斷中將 background 類型的操作提交給線程池對象,並將當前的協程移出運行隊列,添加到 futures 隊列中。然後在每次運行隊列循環後判斷 futures 中的任務是否有完成的(使用的參數為壹旦有任壹任務完成或被取消都返回),如果主線程此時處於將要睡眠的狀態,就等待相應的時間,沒有的話則立刻返回,下次再查詢,完成的任務將其所在協程帶入運行隊列,任務結果通過調度器 send 傳回該協程。