从另一个线程调度异步协程
Scheduling an asyncio coroutine from another thread
我尝试使用 create_task()
从另一个线程安排异步协程。问题是协程没有被调用,至少没有在合理的时间内被调用。
是否有唤醒事件循环或至少指定更短超时的方法?
#!/usr/bin/python3
import asyncio, threading
event_loop = None
@asyncio.coroutine
def coroutine():
print("coroutine called")
def scheduler():
print("scheduling...")
event_loop.create_task(coroutine())
threading.Timer(2, scheduler).start()
def main():
global event_loop
threading.Timer(2, scheduler).start()
event_loop = asyncio.new_event_loop()
asyncio.set_event_loop(event_loop)
event_loop.run_forever()
main()
输出:
scheduling...
scheduling...
scheduling...
scheduling...
我们开始这项工作。这是一个港口。试试吧,因为我有最新版本,我不能真正向你保证它会起作用。
#!/usr/bin/python3
import concurrent.futures
import threading, asyncio
from asyncio import coroutines, futures
def run_coroutine_threadsafe_my(coro, loop):
"""Submit a coroutine object to a given event loop.
Return a concurrent.futures.Future to access the result.
"""
if not coroutines.iscoroutine(coro):
raise TypeError('A coroutine object is required')
future = concurrent.futures.Future()
def callback():
try:
futures._chain_future(asyncio.ensure_future(coro, loop=loop), future)
except Exception as exc:
if future.set_running_or_notify_cancel():
future.set_exception(exc)
raise
loop.call_soon_threadsafe(callback)
return future
event_loop = None
@asyncio.coroutine
async def coro():
print("coroutine called")
def scheduler():
print("scheduling...")
run_coroutine_threadsafe_my(coro(),event_loop)
threading.Timer(2, scheduler).start()
def main():
global event_loop
threading.Timer(2, scheduler).start()
event_loop = asyncio.new_event_loop()
asyncio.set_event_loop(event_loop)
event_loop.run_forever()
main()
根据 Task "this class is not thread safe" 的文档。因此,从另一个线程进行调度预计不会起作用。
我根据此处的答案和评论找到了两个解决方案。
@wind85 回答:直接把create_task
行调用换成asyncio.run_coroutine_threadsafe(coroutine(), event_loop)
调用。需要 Python 3.5.1.
使用call_soon_threadsafe
安排回调,然后创建任务:
def do_create_task():
eventLoop.create_task(coroutine())
def scheduler():
eventLoop.call_soon_threadsafe(do_create_task)
我尝试使用 create_task()
从另一个线程安排异步协程。问题是协程没有被调用,至少没有在合理的时间内被调用。
是否有唤醒事件循环或至少指定更短超时的方法?
#!/usr/bin/python3
import asyncio, threading
event_loop = None
@asyncio.coroutine
def coroutine():
print("coroutine called")
def scheduler():
print("scheduling...")
event_loop.create_task(coroutine())
threading.Timer(2, scheduler).start()
def main():
global event_loop
threading.Timer(2, scheduler).start()
event_loop = asyncio.new_event_loop()
asyncio.set_event_loop(event_loop)
event_loop.run_forever()
main()
输出:
scheduling...
scheduling...
scheduling...
scheduling...
我们开始这项工作。这是一个港口。试试吧,因为我有最新版本,我不能真正向你保证它会起作用。
#!/usr/bin/python3
import concurrent.futures
import threading, asyncio
from asyncio import coroutines, futures
def run_coroutine_threadsafe_my(coro, loop):
"""Submit a coroutine object to a given event loop.
Return a concurrent.futures.Future to access the result.
"""
if not coroutines.iscoroutine(coro):
raise TypeError('A coroutine object is required')
future = concurrent.futures.Future()
def callback():
try:
futures._chain_future(asyncio.ensure_future(coro, loop=loop), future)
except Exception as exc:
if future.set_running_or_notify_cancel():
future.set_exception(exc)
raise
loop.call_soon_threadsafe(callback)
return future
event_loop = None
@asyncio.coroutine
async def coro():
print("coroutine called")
def scheduler():
print("scheduling...")
run_coroutine_threadsafe_my(coro(),event_loop)
threading.Timer(2, scheduler).start()
def main():
global event_loop
threading.Timer(2, scheduler).start()
event_loop = asyncio.new_event_loop()
asyncio.set_event_loop(event_loop)
event_loop.run_forever()
main()
根据 Task "this class is not thread safe" 的文档。因此,从另一个线程进行调度预计不会起作用。
我根据此处的答案和评论找到了两个解决方案。
@wind85 回答:直接把
create_task
行调用换成asyncio.run_coroutine_threadsafe(coroutine(), event_loop)
调用。需要 Python 3.5.1.使用
call_soon_threadsafe
安排回调,然后创建任务:def do_create_task(): eventLoop.create_task(coroutine()) def scheduler(): eventLoop.call_soon_threadsafe(do_create_task)