How can I notify an async routine from a sync routine?
Interview Questions practice on Codemia
Over 8,000 real interview questions from top companies, searchable by company and role.
Introduction
A synchronous routine cannot await, so it cannot notify an async routine by directly calling async code and expecting a result immediately. The usual solution is to hand work or a signal to the event loop through a thread-safe mechanism such as an event, queue, or scheduled coroutine.
Use the Event Loop as the Handoff Point
In Python asyncio, the event loop owns async tasks. If synchronous code needs to notify an async routine, the safe design is:
- async code waits on an event or queue
- sync code signals that event through the loop
- the loop wakes the async task
Here is a complete example using asyncio.Event:
The important call is loop.call_soon_threadsafe(event.set). That schedules the notification safely onto the event loop from synchronous code running in another thread.
Use run_coroutine_threadsafe When the Sync Side Must Trigger Async Work
Sometimes the synchronous routine does not just want to set a flag. It wants to launch a coroutine. In that case, schedule the coroutine onto the loop explicitly:
This is useful when the sync side wants to submit real async work rather than just flip a shared event.
Choose the Right Notification Primitive
The best primitive depends on the shape of the communication:
- use
Eventfor a simple signal - use
Queuewhen data must be passed - use
run_coroutine_threadsafewhen the sync side needs to schedule a coroutine directly
The async routine should wait in an async-friendly way. The sync side should never try to manipulate async objects directly without going through the loop's thread-safe entry points.
Common Pitfalls
The biggest mistake is calling async functions from synchronous code without an event-loop handoff. Creating a coroutine object is not the same as running it.
Another issue is touching asyncio primitives from the wrong thread. If synchronous code runs outside the loop thread, use call_soon_threadsafe or a similar safe bridge.
Developers also sometimes block the event loop while waiting for the sync side to finish. That defeats the purpose of async coordination and can freeze the whole system.
Finally, if the sync side needs a response, design that explicitly. Notification is one-way by default. Request-response usually needs a future, queue, or another callback path.
Summary
- Sync code cannot notify async code by
awaiting directly. - Use the event loop as the handoff boundary.
- '
loop.call_soon_threadsafeis the standard way to signal async primitives from sync code in another thread.' - '
asyncio.run_coroutine_threadsafeis useful when sync code must schedule a coroutine.' - Pick an
Event,Queue, or scheduled coroutine based on whether you need a signal, data, or executable async work. - A thread-safe handoff is more reliable than shared mutable flags polled from async code.
- If sync code needs a result back, pair the notification with a future or queue.
- Keep the event loop free to process the notification promptly.
- Direct cross-thread access to asyncio objects is a correctness bug.
Related reading
- How can I pass a parameter to a Java Thread?
- How can I pool channels in rabbitmq?
- How can I prevent synchronous continuations on a Task?
- How can I process most jobs in parallel but serialize a subset?
- How can I profile a multithread program in Python?
- How can I propagate exceptions between threads?
- How can I raise exception in main thread when using eventlet.GreenPool.spawn
- How can I receive and send over UDP asynchronously with F?
.png&w=3840&q=75)
Tackling System Design Interview Problems
A short course that equips you with the skills to approach system design interviews methodically.
Start the free courseTrack what you have practised
A free account saves your progress, solutions and study plan across every problem on Codemia.
Interview Questions practice on Codemia
Over 8,000 real interview questions from top companies, searchable by company and role.