Strange behaviour when task added to empty loop in different thread(任务添加到不同线程中的空循环时的奇怪行为)
问题描述
我有一个应用程序可以将协程添加到已经运行的事件循环中。 这些协程的参数取决于I/O,并且在我最初使用loop.run_ever()启动事件循环时不可用,所以我稍后添加任务。为了演示这种现象,下面是一些示例代码:
import asyncio
from threading import Thread
from time import sleep
loop = asyncio.new_event_loop()
def foo():
loop.run_forever()
async def bar(s):
while True:
await asyncio.sleep(1)
print("s")
#loop.create_task(bar("A task created before thread created & before loop started"))
t = Thread(target=foo)
t.start()
sleep(1)
loop.create_task(bar("secondary task"))
奇怪的行为是,当调用loop.run_ever()时,当循环中至少有一个任务时,一切都按预期工作。即当注释行未被注释掉时。 但是,如上所述,当它被注释掉时,不会打印任何内容,并且我似乎无法向EVENT_LOOP添加任务。我应该避免在不添加任何任务的情况下调用Run_Foreve()吗?我看不出这有什么问题。在EVENT_LOOP运行后向其添加任务是标准做法,为什么空案例会成为问题?
推荐答案
在Event_loop运行后向其添加任务是标准做法,为什么空案例会成为问题?
因为您应该从运行事件循环的线程添加任务。一般而言,不应混用线程和异步,除非通过为此目的而设计的API,如loop.run_in_executor
。
如果您了解这一点,并且仍然有充分的理由从单独的线程添加任务,请使用asyncio.run_coroutine_threadsafe
。将loop.create_task(bar(...))
更改为:
asyncio.run_coroutine_threadsafe(bar("in loop"), loop=loop)
run_coroutine_threadsafe
以线程安全的方式访问事件循环,并确保事件循环唤醒以通知新任务,即使它与其他任务无关并且只是在等待IO/超时。
bar
碰巧是一个无限协程,它使事件循环每秒唤醒一次。一旦事件循环出于任何原因被唤醒,它就会执行所有可运行的任务,而不管是哪个线程添加了这些任务。但是,依赖于此确实不是一个好主意,因为loop.create_task
不是线程安全的,因此如果它与正在运行的事件循环并行执行,则可能会出现任意数量的争用条件。
这篇关于任务添加到不同线程中的空循环时的奇怪行为的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持编程学习网!
本文标题为:任务添加到不同线程中的空循环时的奇怪行为
基础教程推荐
- Python 的 List 是如何实现的? 2022-01-01
- 如何在Python中绘制多元函数? 2022-01-01
- 使 Python 脚本在 Windows 上运行而不指定“.py";延期 2022-01-01
- 哪些 Python 包提供独立的事件系统? 2022-01-01
- 如何在 Python 中检测文件是否为二进制(非文本)文 2022-01-01
- 使用 Google App Engine (Python) 将文件上传到 Google Cloud Storage 2022-01-01
- 将 YAML 文件转换为 python dict 2022-01-01
- 症状类型错误:无法确定关系的真值 2022-01-01
- 合并具有多索引的两个数据帧 2022-01-01
- 使用Python匹配Stata加权xtil命令的确定方法? 2022-01-01