异步Queue.get延迟

时间:2018-12-07 12:06:23

标签: python python-3.x queue python-asyncio

我有以下代码:

import asyncio
import threading
import time

q = asyncio.Queue()

async def ping():
    while True:
        await asyncio.sleep(10)
        print("ping")

async def rcv():
    while True:
        item = await q.get()
        print("got item")

async def run():
    tasks = [asyncio.ensure_future(ping()), asyncio.ensure_future(rcv())]
    await asyncio.wait(tasks, return_when="FIRST_EXCEPTION")

loop = asyncio.get_event_loop()

def run_loop():
    asyncio.set_event_loop(loop)
    loop.run_until_complete(run())

threading.Thread(target=run_loop).start()

while True:
    time.sleep(2)
    q.put_nowait("item")
    print("item added")

我希望每2秒(每个时间项都添加到队列中),我将看到输出:

item added
sleeping 2 seconds
got item

每隔10秒我还会看到ping

但是,这是我得到的(重复)输出:

sleeping 2 seconds
item added
sleeping 2 seconds
item added
sleeping 2 seconds
item added
sleeping 2 seconds
item added
sleeping 2 seconds
got item
got item
got item
got item
ping
item added
sleeping 2 seconds
...

似乎item = await q.get()部分也从asyncio.sleep(10)函数中等待ping

我想念什么?以及如何修复代码以便获得预期的输出?

谢谢!

1 个答案:

答案 0 :(得分:2)

  

我想念什么?以及如何修复代码以便获得预期的输出?

由于您是在单独的线程中运行事件循环,因此需要将q.put_nowait("item")更改为:

loop.call_soon_threadsafe(q.put_nowait, "item")

原因是异步代码(故意)不是线程安全的,因此使用put_nowait不会通知事件循环新项目已入队。