【问题标题】:Asyncio put to queue.QueueAsyncio 放入 queue.Queue
【发布时间】:2018-04-13 23:30:48
【问题描述】:

一个非常简单的问题,我无法找到答案:

如果我想在自己的线程中运行 asyncio 事件循环,并将消息发送回主线程,它可以使用 queue.Queue 实例吗?

如果这确实可行且安全,是否有更好的方法将消息从非主线程中的异步循环传递到主线程?

这是一个玩具示例,似乎可行:

import asyncio
from queue import Queue
import threading

queue_to_main = Queue()


async def coro1():

    for i in range(5):
        queue_to_main.put_nowait(i)
        await asyncio.sleep(1)

    queue_to_main.put_nowait("STOP")


def runloop():
    loop = asyncio.new_event_loop()
    asyncio.set_event_loop(loop)
    try:
        loop.run_until_complete(coro1())
    finally:
        loop.close()


t1 = threading.Thread(target=runloop)
t1.start()

while True:
    item = queue_to_main.get()
    if item == "STOP":
        break
    print(item)

t1.join()

我设想的场景是在它自己的线程中运行一个 aiohttp 服务器,但由于某些请求而让其与主线程通信。

【问题讨论】:

  • 您是否特别想避免使用asyncio.Queue
  • 不是特别 - 如果在这种情况下最终成为最好的做事方式,我会很乐意使用它。但是,我想从主线程中的asyncio.Queue 实例获取项目会有些复杂,因为asyncio.Queue 不是线程安全的?我想您可能需要执行以下操作:item = asyncio.run_coroutine_threadsafe(my_aio_queue.get(), loop).result()?
  • 相关:janus

标签: python multithreading thread-safety python-3.5 python-asyncio


【解决方案1】:

asyncio.Queue 旨在用于单个事件循环内。 队列不是环间通信原语。

此外,您不应启动多个并行循环,每个循环都在自己的线程中。它是反模式(至少对于 Python 而言)。

【讨论】:

  • 这应该以什么方式回答这个问题?我自己也有同样的问题,我需要在主线程的事件循环中运行的异步代码和在该事件循环内的执行器(嵌入式线程/进程)中运行的同步代码之间建立同步通信。在过去的三天里,我一直在深入研究 asyncio 的内部工作原理并阅读官方文档,就像 OP 一样,我似乎找不到任何解释同步和异步线程之间的线程间/进程间通信如何最好的示例实施..
  • 我能找到的唯一解决方案是; 1)使用普通(线程安全)队列,然后将 .put() 和 .get() 方法包装在执行程序中以在异步代码中运行,并在正常同步代码中使用队列的另一端。 2)从带参数的同步线程调度异步协程执行(使用线程安全方法),等待协程返回的Future对象的结果,在异步线程中成功执行后。 3) 在线程之间使用套接字或管道(仅限 Unix)。以上所有对我来说都像是黑客攻击......
猜你喜欢
  • 2012-12-12
  • 2017-12-22
  • 1970-01-01
  • 1970-01-01
  • 2020-04-20
  • 1970-01-01
  • 2012-01-02
  • 1970-01-01
  • 2015-09-30
相关资源
最近更新 更多