Кажется, что обратный вызов не выполняется при подключении к другому потоку - PullRequest
0 голосов
/ 11 июля 2019

Что я хочу сделать, это в консоли Python :

  1. Создать будущее asyncio
  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)

Моя цель высокого уровня - играть сФьючерсы и Asyncio непосредственно в консоли , чтобы лучше понять это.

1 Ответ

0 голосов
/ 11 июля 2019

Обратите внимание при игре с 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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...