连接到另一个线程时似乎不执行回调

时间:2019-07-11 12:03:46

标签: python multithreading future asyncio

我想做的是,在Python控制台中

  1. 创建一个异步的未来
  2. 为这个未来添加回调
  3. 设置未来值(并同时获得回调结果)

为此,我在 Python控制台中尝试了

from threading import Thread
import asyncio

def start_loop(loop):
    asyncio.set_event_loop(loop)
    loop.run_forever()

new_loop = asyncio.new_event_loop()
t = Thread(target=start_loop, args=(new_loop,))
t.start()

fut = new_loop.create_future()
fut.add_done_callback(lambda _: print("Hey"))

fut.set_result(True)

我希望打印出“嘿”,但实际上我什么也没得到。

其他信息:

当我这样做时:

import asyncio

loop = asyncio.get_event_loop()

fut = loop.create_future()
fut.add_done_callback(lambda x: print("Hey"))

fut.set_result(True)

loop.run_forever()

我得到了预期的结果,但是当未来已经确定时,我不得不打电话给run_forever

我的问题是:

  1. 为什么我的第一段代码没有按预期完成任务?
  2. 是否存在以下现有的假设语法?
import asyncio

loop = asyncio.get_event_loop()

fut = loop.create_future()

# Hypothetical part
loop.run_forever_in_background()
# End of hypothetical part

fut.add_done_callback(lambda x: print("Hey"))

fut.set_result(True)

我的高级目标是直接在控制台中玩期货和异步交易,以更好地理解期货和异步交易。

1 个答案:

答案 0 :(得分:0)

在多线程上下文中玩asyncio循环,期货等时要引起注意。

  

几乎所有asyncio对象都是不是线程安全的,这是   通常没有问题,除非有可以从中使用它们的代码   在任务或回调之外。
  ...
  要从其他操作系统线程安排协程对象,   应该使用run_coroutine_threadsafe()函数。它返回一个   concurrent.futures.Future访问结果:

from threading import Thread
import asyncio

def start_loop(loop):
    asyncio.set_event_loop(loop)
    loop.run_forever()

new_loop = asyncio.new_event_loop()
t = Thread(target=start_loop, args=(new_loop,))
t.start()

async def add_future():
    fut = new_loop.create_future()
    fut.add_done_callback(lambda _: print("Hey"))
    fut.set_result(True)


asyncio.run_coroutine_threadsafe(add_future(), loop=new_loop)

测试:

$ python3 test.py 
Hey

另一个选择是使用loop.call_soon_threadsafe(callback, *args, context=None)

https://docs.python.org/3/library/asyncio-dev.html#asyncio-multithreading