python - 如何为异步生成器提供来自 python.net 的事件
问题描述
我通过 Python for .Net 在 Python 3.6 中使用第三方 .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
and并设置计时器不会这样做,但是有没有一种简单的方法来实现这一点?yield
await
解决方案
由于“异步”数据来自另一个线程,因此您需要在 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())
推荐阅读
- javascript - 从 Flask python 后端将数据流式传输到 axios Javascript 前端
- c# - 当我尝试在 MVVM WPF 中使用命令修改对象时,为什么在视图模型中出现空错误?
- r - 根据与r中其他数据帧中日期的差异将日期转换为时间序列
- asp.net-core - 在 OnModelCreating 之外添加全局过滤器
- java - 使用 Firestore 事务更新多个文档
- java - 如何在android中使用kotlin有效地避免多次点击菜单项
- html - Angular 9 Reactive Form - Array Form - 选择一个值以自动填充同一行中的其他单元格
- python - 用正则表达式替换python中两个标签周围的文本
- python - 如何使用环境变量子处理调用?
- r - 这个速度、年龄、里程和年份的公式是什么意思?