簡體   English   中英

python asyncio取消run_in_executor阻塞主線程

[英]python asyncio cancel run_in_executor blocks mainthread

通過 asyncio run_in_executor 啟動同步功能然后取消它時,我看到了不需要的行為。 ThreadPoolExecutor(以及 ProcessPoolExecutor)上下文管理器將在退出時調用 executor.shutdown 並等待所有掛起的工作完成(在其線程上使用 join() )。

我原以為連接是異步管理的,因此其他任務可能不會被阻止,但我發現連接是同步調用的。

run_in_executor 的實現應該考慮這個嗎? 或者是應該處理的事情(比如在線程上調用 executor.shutdown )?

此示例代碼啟動 2 個任務並取消在子線程上運行的一個,從日志中可以看出子線程是取消后唯一執行的代碼:

from time import sleep
from asyncio import (
    get_running_loop, 
    sleep as async_sleep,
    get_event_loop,
    create_task
)
from concurrent.futures import ThreadPoolExecutor
from datetime import datetime
​
​
def sync_watchdog():
    for _ in range(30):
        print(f'{datetime.now()} I am in a thread')
        sleep(1)
​
​
async def inthread():
    with ThreadPoolExecutor() as executor:
        await get_running_loop().run_in_executor(executor, sync_watchdog)
​
async def watchdog():
    for _ in range(30):
        print(f'{datetime.now()} I am an async watchdog')
        await async_sleep(1)
​
​
async def run():
    intread_task = create_task(inthread())
    watchdog_task = create_task(watchdog())
​
    await async_sleep(2)
​
    print('canceling task with subthread')
    intread_task.cancel()
​
    await async_sleep(10)
​
​
get_event_loop().run_until_complete(run())

這將輸出:

2021-10-27 17:08:16.796171 I am in a thread
2021-10-27 17:08:16.796248 I am an async watchdog
2021-10-27 17:08:17.797205 I am an async watchdog
2021-10-27 17:08:17.797310 I am in a thread
canceling task with subthread
2021-10-27 17:08:18.797990 I am an async watchdog
2021-10-27 17:08:18.798430 I am in a thread
2021-10-27 17:08:19.799037 I am in a thread
2021-10-27 17:08:20.800327 I am in a thread
2021-10-27 17:08:21.801521 I am in a thread
2021-10-27 17:08:22.802819 I am in a thread
2021-10-27 17:08:23.804014 I am in a thread
2021-10-27 17:08:24.805434 I am in a thread
2021-10-27 17:08:25.806640 I am in a thread
2021-10-27 17:08:26.807797 I am in a thread
2021-10-27 17:08:27.808880 I am in a thread
2021-10-27 17:08:28.810305 I am in a thread
2021-10-27 17:08:29.811247 I am in a thread
2021-10-27 17:08:30.811901 I am in a thread
2021-10-27 17:08:31.813083 I am in a thread
2021-10-27 17:08:32.814301 I am in a thread
2021-10-27 17:08:33.815499 I am in a thread
2021-10-27 17:08:34.816565 I am in a thread
2021-10-27 17:08:35.817920 I am in a thread
2021-10-27 17:08:36.818478 I am in a thread
2021-10-27 17:08:37.819603 I am in a thread
2021-10-27 17:08:38.820844 I am in a thread
2021-10-27 17:08:39.822042 I am in a thread
2021-10-27 17:08:40.822491 I am in a thread
2021-10-27 17:08:41.823690 I am in a thread
2021-10-27 17:08:42.824871 I am in a thread
2021-10-27 17:08:43.826012 I am in a thread
2021-10-27 17:08:44.826516 I am in a thread
2021-10-27 17:08:45.827698 I am in a thread
2021-10-27 17:08:46.829813 I am an async watchdog

長話短說: .shutdown()僅取消掛起的執行程序任務,尚未運行。

那是因為threading.Thread沒有.cancel().abort()方法。 如果要停止正在運行的線程中的循環,請創建一個標志,在每次迭代中檢查它,如果需要停止則提高該標志。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM