首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >python asyncio取消run_in_executor阻塞主线程

python asyncio取消run_in_executor阻塞主线程
EN

Stack Overflow用户
提问于 2021-10-28 20:18:02
回答 1查看 125关注 0票数 1

当通过异步run_in_executor启动同步功能,然后取消它时,我看到了一个不想要的行为。ThreadPoolExecutor (以及ProcessPoolExecutor)上下文管理器将在退出时调用executor.shutdown,并等待所有挂起的工作完成(在其线程上使用join() )。

我原本希望连接是异步管理的,这样其他任务就不会被阻塞,但我发现连接是同步调用的。

run_in_executor的实现应该考虑到这一点吗?或者这是应该处理的(就像在线程上调用executor.shutdown一样)?

这个示例代码启动了两个任务,并取消了在子线程上运行的任务,从日志中可以看到,在取消之后,子线程是唯一执行的代码:

代码语言:javascript
复制
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())

这将输出:

代码语言:javascript
复制
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
EN

回答 1

Stack Overflow用户

发布于 2021-10-29 09:09:17

长话短说:.shutdown()只取消尚未运行的挂起的执行器任务。

这是因为threading.Thread没有.cancel().abort()方法。如果您想要停止正在运行的线程中的循环,请创建一个标志,在每次迭代中检查它,如果需要停止,则提升该标志。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/69760390

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档