当任务添加到不同线程中的空循环时,行为异常

JSStuball

我有一个将协程添加到已经运行的事件循环中的应用程序。这些协程的参数取决于I / O,并且在我最初启动事件循环(使用loop.run_forever())时不可用,因此稍后再添加任务。为了演示这种现象,下面是一些示例代码:

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_forever()时,如果循环中至少有一个任务,那么一切都会按预期进行即,当注释行未注释掉时。

但是,当它被注释掉时,如上所示,什么也没有打印,看来我无法向event_loop添加任务。我应该避免在不添加单个任务的情况下调用run_forever()吗?我不明白为什么这应该是一个问题。在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它不是线程安全的,因此,如果它与正在运行的事件循环并行执行,则可能存在许多竞争条件。

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章

Java:线程:将带有 ID 的元素添加到不同线程的列表中

我如何从Vala中的不同线程添加到GLib.List

在不同线程中运行任务

停止不同线程中的无限循环

将来自不同线程的值添加到全局集中,并等待所有线程完成

C#-在不同线程中添加UserControl即使在调用后也会导致异常

在不同线程中更改标志时,while循环未结束

将新对象添加到DbContext时,Entity Framework中的空引用异常

在不同线程中运行协程循环

从多个线程添加到 List<String> 时的预期行为是什么?

填充在不同线程中的列表在调用者线程中显示为空-Java

将变量添加到processBuilder时,线程“ main”中发生异常

在Spring Webflux带注释的控制器中的不同线程中运行任务

VB.NET 加载 Datagridview 在从不同线程调用它时抛出异常

将元素添加到列表时出现空指针异常

在NetBeans中将ImageIcon添加到jbutton时,出现空指针异常

尝试将组件添加到选项卡时,Vaadin空指针异常

尝试将数据从sqlite添加到微调器时出现空指针异常

尝试将List <String>添加到HashMap时出现空点异常

如何将任务添加到在另一个线程上运行的Tokio事件循环中?

Java访问不同线程中的对象

从JavaFX中的不同线程更新UI

不同线程中SharedPreference的访问值

从不同线程中的QFile读取

QSqlDatabase不同线程中的并发查询

在不同线程中执行 lambda 函数

将延迟添加到android中的循环,而不会延迟UI线程

Python 3.5 asyncio在事件循环中从不同线程中的同步代码执行协程

将第一行添加到空数据时,行号不同(NA与1)