线程在各自的事件循环中对回调进行排队,但它们在实际执行事件循环之前退出,因此回调永远不会执行.此外,您不需要call_soon_threadsafe
,因为您正在从事件循环运行(或者更确切地说,将运行)的同一线程调用回调.
此代码打印预期的输出:
import asyncio
from threading import Thread
def hello(thread_name):
print('hello from thread {}!'.format(thread_name))
event_loop_a = asyncio.new_event_loop()
event_loop_b = asyncio.new_event_loop()
def callback_a():
asyncio.set_event_loop(event_loop_a)
asyncio.get_event_loop().call_soon(lambda: hello('a'))
event_loop_a.run_forever()
def callback_b():
asyncio.set_event_loop(event_loop_b)
asyncio.get_event_loop().call_soon(lambda: hello('b'))
event_loop_b.run_forever()
thread_a = Thread(target=callback_a, daemon=True)
thread_b = Thread(target=callback_b, daemon=True)
thread_a.start()
thread_b.start()
call_soon_threadsafe
的一个更典型的用例,更符合您的 idea ,是向另一个线程中运行的事件循环提交回调(或使用asyncio.run_coroutine_threadsafe
的协同路由).下面是一个例子:
import asyncio, threading
def hello(thread_name):
print('hello from thread {}!'.format(thread_name))
event_loop_a = asyncio.new_event_loop()
event_loop_b = asyncio.new_event_loop()
def run_loop(loop):
asyncio.set_event_loop(loop)
loop.run_forever()
threading.Thread(target=lambda: run_loop(event_loop_a)).start()
threading.Thread(target=lambda: run_loop(event_loop_b)).start()
event_loop_a.call_soon_threadsafe(lambda: hello('a'))
event_loop_b.call_soon_threadsafe(lambda: hello('b'))
event_loop_a.call_soon_threadsafe(event_loop_a.stop)
event_loop_b.call_soon_threadsafe(event_loop_b.stop)
在这种情况下,很少需要有多个事件循环线程——通常只创建一个,并允许该线程满足所有asyncio需求.毕竟,能够在单个事件循环中承载大量任务是asyncio的优点之一.