在异步任务之间自由切换的正确方法是什么?

2024-01-05

假设我有一些异步运行的任务。它们可能是完全独立的,但我仍然想设置任务暂停的点,以便它们可以同时运行。

并发运行任务的正确方法是什么?我目前正在使用await asyncio.sleep(0),但我觉得这增加了很多开销。

import asyncio

async def do(name, amount):
    for i in range(amount):
        # Do some time-expensive work
        print(f'{name}: has done {i}')

        await asyncio.sleep(0)

    return f'{name}: done'

async def main():
    res = await asyncio.gather(do('Task1', 3), do('Task2', 2))
    print(*res, sep='\n')

loop = asyncio.get_event_loop()

loop.run_until_complete(main())

Output

Task1: has done 0
Task2: has done 0
Task1: has done 1
Task2: has done 1
Task1: has done 2
Task1: done
Task2: done

如果我们使用简单的生成器,一个空的yield会暂停任务流程,没有任何开销,但是是空的await无效。

在没有开销的情况下设置此类断点的正确方法是什么?


正如评论中提到的,通常 asyncio 协程会在等效同步代码中阻塞或休眠的调用上自动挂起。在您的情况下,协程是受 CPU 限制的,因此等待阻塞调用是不够的,它需要偶尔放弃对事件循环的控制以允许系统的其余部分运行。

显式收益在协作多任务处理中并不罕见,并且使用await asyncio.sleep(0)为此目的将按预期工作 https://github.com/python/asyncio/issues/284,它确实存在风险:睡眠太频繁,并且由于不必要的切换而减慢了计算速度;睡眠太少,并且您在单个协程中花费太多时间,从而占用了事件循环。

asyncio 提供的解决方案是将 CPU 密集型代码卸载到线程池,使用run_in_executor https://docs.python.org/3/library/asyncio-eventloop.html#asyncio.AbstractEventLoop.run_in_executor。等待它会自动挂起协程,直到 CPU 密集型任务完成,无需任何中间轮询。例如:

import asyncio

def do(id, amount):
    for i in range(amount):
        # Do some time-expensive work
        print(f'{id}: has done {i}')

    return f'{id}: done'

async def main():
    loop = asyncio.get_event_loop()
    res = await asyncio.gather(
        loop.run_in_executor(None, do, 'Task1', 5),
        loop.run_in_executor(None, do, 'Task2', 3))
    print(*res, sep='\n')

loop = asyncio.get_event_loop()
loop.run_until_complete(main())
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

在异步任务之间自由切换的正确方法是什么? 的相关文章

随机推荐

  • 如何获取 Ant 中的 basedir 路径中最后一个文件夹的名称?

    假设我的 basedir c projects myapp 1 2 我怎样才能在房产中获得 1 2 Check this http ant apache org manual Tasks basename html out
  • Android 完全透明的状态栏?

    I ve searched the documentation but only found this Link http developer android com about versions android 4 4 html UI W
  • JavaScript 中的原型不好吗?

    In Felix 的 Node js 风格指南 http nodeguide com style html它说 不要扩展任何原型 对象 尤其是本地对象 那里 地狱里有一个特殊的地方等待着 如果你不遵守这条规则 本文 http howtono
  • 整数如何存储在内存中?

    当我阅读一篇有关大 小端的文章时 我很困惑 代码如下 include
  • 在 Centos 6.3 中使用 php-ldap

    我正在尝试使用 php 构建 LDAP 界面 但遇到了这个奇怪的问题 我已经在我的基本 php 安装上使用 yum 安装了 php ldap 包 但每当我调用 ldap connect 时 它都会说该函数未定义 看到 phpinfo 我可以
  • 正则表达式逗号后面没有空格

    我目前正在尝试创建一个表达式 以捕获所有后面没有空格的逗号以及所有冒号 我试过了 s 很接近 但似乎也抓住了逗号后面没有空格的字符 我也尝试过 s 它将抓取所有冒号和所有逗号 其后有一个空格以及空格 我希望选择的内容包含在下面的 中 你好
  • 如何更改视频方向

    我目前有一个 iPhone 应用程序 可以让用户拍摄视频 将其上传到服务器 并允许其他人从该应用程序查看他们的视频 从来没有遇到过视频方向的问题 直到我制作一个网站来观看不同的视频 以及其他内容 我使用来自网络服务的视频 并使用 video
  • 无法解析模块react/lib/ReactUpdates

    我正在克隆一个项目 步骤是 npm i 反应本机链接 当我运行它时react native run ios我有一个问题RCTWebSocket图书馆 如果你稍微搜索一下 这个问题很容易解决 只需要删除 2 个编译器标志 在Custom Co
  • 如何从python Flask中的mongodb mlab返回包含键中特定关键字的文档[重复]

    这个问题在这里已经有答案了 我在 mongodb 中有这个集合 我的收藏 id 5ad2079019551a2108588add brand name MAZOLA LIZA name pyd id 5ad2079019551a210858
  • “ng build”与“ng build --prod”不一致

    我正在开发一个有角度的应用程序 Using Angular 5 2 5 角度 CLI1 6 8 当我执行命令时 ng build 我没有收到任何错误 但是当我尝试生产构建时 ng build prod 我收到错误 属性 someProper
  • Spring启动错误:java.lang.ArrayStoreException:sun.reflect.annotation.TypeNotPresentExceptionProxy

    我想使用 spring boot 来启动我的应用程序 但是在我在 pom xml 添加一些相关的 jar 后 它返回此错误 我感谢可能是由一些冲突 jar 引起的 应用程序 java package com mm application i
  • 检查日期是否是过去的Javascript

    全部 我使用 jQuery UI 作为日期选择器 我正在尝试使用 javascript 检查用户输入的日期是否是过去的日期 这是我的表单代码
  • 计算值太大而无法求幂的马尔可夫链概率

    我使用公式 exp X 作为马尔可夫链的速率 因此选择一个链接相对于另一个链接的比率是 exp X1 exp X2 我的问题是有时X很大 所以exp X 会超出范围double 或者 给定一个 X i 数组 其中一些 X i 太大 以致 e
  • 如何查看矩阵乘法的进度?

    我现在只需要显示矩阵乘法的中间进度 for unsigned int col 0 col
  • uitableview 部分标题内的日期格式,请帮忙

    首先我要说的是 我对 iPhone 开发非常陌生 但我非常努力地学习 因此 非常感谢你们专业人士愿意分享的任何帮助 所以我有一个问题 如果有人能回答我的话那就太棒了 我正在研究更多一项核心数据 并一直在使用苹果开发者网站上找到的核心数据书籍
  • 无法访问 usort() 函数调用内部的全局变量

    我正在尝试使用usort 并在其函数范围内利用全局变量 但没有成功 我已将代码简化为简单的框架以展示我的意思 testglobal 1 function cmp a b global testglobal echo hi testgloba
  • 对哈德逊的“圣杯战争”自动回复“是”

    我们正在使用 grails war 来构建对 hudson 的战争 然后将另一项工作部署到我们的测试环境 问题在于 当 grails war 遇到插件升级时 它会不断要求用户升级某些插件 有没有办法对所有用户输入响应 y 我尝试过 non
  • 服务器端病毒扫描[关闭]

    Closed 这个问题不符合堆栈溢出指南 help closed questions 目前不接受答案 我们不允许提出寻求书籍 工具 软件库等推荐的问题 您可以编辑问题 以便用事实和引文来回答 这个问题似乎不是关于主要由程序员使用的特定编程问
  • 如何读取数据文件?

    如果我有数据file txt我想使用以下命令将数据读取到变量中 set 我怎样才能做到这一点 如何将一行移动到另一行 根据您的评论从文件中读取两行 echo off setLocal EnableDelayedExpansion for f
  • 在异步任务之间自由切换的正确方法是什么?

    假设我有一些异步运行的任务 它们可能是完全独立的 但我仍然想设置任务暂停的点 以便它们可以同时运行 并发运行任务的正确方法是什么 我目前正在使用await asyncio sleep 0 但我觉得这增加了很多开销 import asynci