4

I am using a third party .Net library in Python 3.6 via Python for .Net which uses EventHandlers to provide asynchronous data to my application, similar to the toy example below:

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

I would like to get this data into an asynchronous generator, something like:

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

Obiviously just throwing asyc and yield on the event handler function and awaiting the timer won't do it, but is there a straightforward means of accomplishing this?

1 Answer 1

4

Since the "asynchronous" data comes from another thread, you will need a bridge between asyncio and the thread that invokes tock. On the asyncio side, you will need to implement an async generator and iterate over it with an async for loop. For example (untested):

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())
Sign up to request clarification or add additional context in comments.

1 Comment

Thank you, that solution works (after adding the import asyncio that I forgot initially)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.