如何向异步生成器提供来自python.n的事件

2024-06-13 13:12:01 发布

您现在位置:Python中文网/ 问答频道 /正文

我通过Python for.Net使用Python 3.6中的第三方.Net库,它使用事件处理程序向我的应用程序提供异步数据,类似于下面的玩具示例:

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

我想把这些数据输入异步生成器,比如:

^{pr2}$

显然,仅仅在事件处理程序函数上抛出asycyield,并对计时器进行await,显然不能做到这一点,但是有没有一种简单的方法来实现这一点呢?在


Tags: 数据importtrue应用程序处理程序示例fornet
1条回答
网友
1楼 · 发布于 2024-06-13 13:12:01

由于“异步”数据来自另一个线程,因此您需要在asyncio和调用tock的线程之间建立一个桥。在异步端,您将需要实现一个异步生成器,并使用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())

相关问题 更多 >