1

I have an async coroutine that I want to terminate using a timer/thread. The coroutine is based of this example from aiortc.

args = parse_args()
client = Client(connection, media, args.role)

# run event loop
loop = asyncio.get_event_loop()

try:
    timer = None
    if args.timeout:
        print("Timer started")
        timer = threading.Timer(args.timeout, loop.run_until_complete, args=(client.close(),))
        timer.start()

    loop.run_until_complete(client.run())

    if timer:
        timer.join()
except KeyboardInterrupt:
    pass
finally:
    # cleanup
    loop.run_until_complete(client.close())

This does not work and raises RuntimeError('This event loop is already running')

Why does this raise the error? My guess is that it's because the loop is running on a different thread. However, creating a new loop doesn't work as it gets a future attached to a different loop.

def timer_callback():
    new_loop = asyncio.new_event_loop()
    new_loop.run_until_complete(client.close())

Following that, how can I use a timer to end the script?

2 Answers 2

2

Following that, how can I use a timer to end the script?

You can call asyncio.run_coroutine_threadsafe() to submit a coroutine to an event loop running in another thread:

    if args.timeout:
        print("Timer started")
        timer = threading.Timer(
            args.timeout,
            asyncio.run_coroutine_threadsafe,
            args=(client.close(), loop),
        )
        timer.start()

Note, however, that since you're working with asyncio, you don't need a dedicated thread for the timer, you could just create a coroutine and tell it to wait before doing something:

    if args.timeout:
        print("Timer started")
        async def close_after_timeout(): 
            await asyncio.sleep(args.timeout)
            await client.close()
        loop.create_task(close_after_timeout())
Sign up to request clarification or add additional context in comments.

Comments

0

This isn't the general solution that I was looking for, I added a timeout variable to the client constructor, and within client.run() I added asyncio.sleep(timeout) which would exit the loop. This is enough for my purposes.

Comments

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.