如何为异步生成器提供来自 python.net 的事件
How to feed an async generator with events from python.net
我通过 Python 在 Python 3.6 中使用第三方 .Net 库 for .Net,它使用 EventHandlers 向我的应用程序提供异步数据,类似于下面的玩具示例:
import clr
from System import Timers
def tock(__, args):
print(args.SignalTime)
timer = Timers.Timer()
timer.Interval = 1000
timer.Elapsed += tock
timer.Enabled = True
while True:
pass
我想将此数据放入异步生成器中,例如:
import clr
from System import Timers
async def tock(__, args):
yield args.SignalTime
async def main():
result = await tock
print(result)
timer = Timers.Timer()
timer.Interval = 1000
timer.Elapsed += tock
timer.Enabled = True
while true:
result = await timer
print result
显然只是在事件处理函数上抛出 asyc
和 yield
并 await
计时器不会这样做,但是有没有一种直接的方法来完成这个?
由于 "asynchronous" 数据来自另一个线程,您需要在 asyncio 和调用 tock
的线程之间建立桥梁。在 asyncio 方面,您需要实现一个异步生成器并使用 async for
循环对其进行迭代。例如(未经测试):
import clr, asyncio
from System import Timers
def adapt_sync_to_async():
# Adapt a series of sync callback invocations to an async
# iterator. Returns an async iterator and a feed callback
# such that the async iterator will produce a new item
# whenever the feed callback is fed one.
loop = asyncio.get_event_loop()
queue = asyncio.Queue()
def feed(item):
loop.call_soon_threadsafe(queue.put_nowait, item)
async def drain():
while True:
yield await queue.get()
return drain, feed
tock, feed_tock = adapt_sync_to_async()
async def main():
async for result in tock():
print(result)
timer = Timers.Timer()
timer.Interval = 1000
timer.Elapsed += lambda _, args: feed_tock(args.SignalTime)
timer.Enabled = True
asyncio.get_event_loop().run_until_complete(main())
我通过 Python 在 Python 3.6 中使用第三方 .Net 库 for .Net,它使用 EventHandlers 向我的应用程序提供异步数据,类似于下面的玩具示例:
import clr
from System import Timers
def tock(__, args):
print(args.SignalTime)
timer = Timers.Timer()
timer.Interval = 1000
timer.Elapsed += tock
timer.Enabled = True
while True:
pass
我想将此数据放入异步生成器中,例如:
import clr
from System import Timers
async def tock(__, args):
yield args.SignalTime
async def main():
result = await tock
print(result)
timer = Timers.Timer()
timer.Interval = 1000
timer.Elapsed += tock
timer.Enabled = True
while true:
result = await timer
print result
显然只是在事件处理函数上抛出 asyc
和 yield
并 await
计时器不会这样做,但是有没有一种直接的方法来完成这个?
由于 "asynchronous" 数据来自另一个线程,您需要在 asyncio 和调用 tock
的线程之间建立桥梁。在 asyncio 方面,您需要实现一个异步生成器并使用 async for
循环对其进行迭代。例如(未经测试):
import clr, asyncio
from System import Timers
def adapt_sync_to_async():
# Adapt a series of sync callback invocations to an async
# iterator. Returns an async iterator and a feed callback
# such that the async iterator will produce a new item
# whenever the feed callback is fed one.
loop = asyncio.get_event_loop()
queue = asyncio.Queue()
def feed(item):
loop.call_soon_threadsafe(queue.put_nowait, item)
async def drain():
while True:
yield await queue.get()
return drain, feed
tock, feed_tock = adapt_sync_to_async()
async def main():
async for result in tock():
print(result)
timer = Timers.Timer()
timer.Interval = 1000
timer.Elapsed += lambda _, args: feed_tock(args.SignalTime)
timer.Enabled = True
asyncio.get_event_loop().run_until_complete(main())