Reputation: 2605
This is a sample program of something I'm trying to do in a main project, but the main idea is that I created a task using a asyncio.create_task. I want to then pause that task later on in the code when some event happens. In this sample code, asyncio.create_task starts task_tic_tock and prints "tic-tock". Later in the code, when other_task has a count that is divisible by 3, it takes a lock and starts task_tic_tock with the parameter being False. I'm not sure a lock is the best thing to use, but the behavior I am hoping for is for it to print "In new count" and "print val is now false", but not "tic-"tock". Once the lock ends I want it to resume printing "tic_tock".
import asyncio
lock = asyncio.Lock()
def task_tic_tock(print_val):
if print_val:
print("tic-tock")
else:
print("Print val is now false")
async def start_tic_tock(print_val):
while True:
task_tic_tock(print_val)
await asyncio.sleep(1)
async def other_task():
count = 0
while True:
count = count + 1
if count % 3 == 0:
async with lock:
task_tic_tock(False)
new_count = 5
while new_count > 0:
print("In new count")
new_count = new_count - 1
await asyncio.sleep(1)
await asyncio.sleep(1)
print("Other task running")
await asyncio.sleep(1)
async def main():
print_val = asyncio.create_task(start_tic_tock(True))
await asyncio.gather(other_task(), print_val)
asyncio.run(main())
How does create_task work and is it possible to pause it for a period of time while another task is going on? Any help would be appreciated!
Upvotes: 1
Views: 4569
Reputation: 2733
You can achieve what you want with a lock. The issue with your code is that you never acquire the lock in start_tic_tock
, so you have no way to 'pause' that coroutine based on the lock you acquire in other_task
.
You can fix this by making your start_tic_tock
method acquire the lock as follows:
async def start_tic_tock(print_val):
while True:
async with lock:
task_tic_tock(print_val)
await asyncio.sleep(1)
That said an Event may be better suited to what you want. Events are explicitly for notifying tasks when a condition is achieved. Full code is below using an event. Note that when you create an Event
or a Lock
globally as you do in the above code you might be creating a new event loop. asyncio.run
always creates a new loop which means you could have two loops running and this can lead to exceptions. In the below I've explicitly created a loop to avoid these errors, you'll need to refactor a bit to use asyncio.run
again.
import asyncio
loop = asyncio.new_event_loop()
event = asyncio.Event(loop=loop)
async def start_tic_tock(print_val):
while True:
await event.wait()
task_tic_tock(print_val)
await asyncio.sleep(1)
async def other_task():
count = 0
while True:
count = count + 1
if count % 3 == 0:
event.clear()
task_tic_tock(False)
new_count = 5
while new_count > 0:
print("In new count")
new_count = new_count - 1
await asyncio.sleep(1)
event.set()
await asyncio.sleep(1)
print("Other task running")
await asyncio.sleep(1)
async def main():
print_val = asyncio.create_task(start_tic_tock(True))
await asyncio.gather(other_task(), print_val)
loop.run_until_complete(main())
The above prints:
Print val is now false
In new count
In new count
In new count
In new count
In new count
tic-tock
tic-tock
tic-tock
Upvotes: 3