async tasks
task cancellation
asynchronous programming
concurrency
programming best practices

Cancel all async tasks

Master System Design with Codemia

Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.

Introduction

Canceling all asynchronous tasks only makes sense once you define the runtime model, because every async platform does it differently. In Python asyncio, task cancellation is cooperative: you request cancellation, and each task must reach an await point and handle CancelledError correctly before it truly stops.

Cancel Tasks Explicitly in asyncio

In Python, each running asynchronous operation can be wrapped in an asyncio.Task. To cancel many of them, keep references to those tasks and call .cancel() on each one.

python
1import asyncio
2
3
4async def worker(name):
5    try:
6        while True:
7            print(f"{name} working")
8            await asyncio.sleep(1)
9    except asyncio.CancelledError:
10        print(f"{name} cancelled")
11        raise
12
13
14async def main():
15    tasks = [
16        asyncio.create_task(worker("A")),
17        asyncio.create_task(worker("B")),
18        asyncio.create_task(worker("C")),
19    ]
20
21    await asyncio.sleep(2)
22
23    for task in tasks:
24        task.cancel()
25
26    await asyncio.gather(*tasks, return_exceptions=True)
27
28
29asyncio.run(main())

Calling .cancel() does not destroy the task instantly. It injects a cancellation request that becomes visible when the task resumes execution at an await point.

Use asyncio.all_tasks() During Shutdown

If you want to cancel nearly everything running in the current loop, asyncio.all_tasks() is useful. The key detail is that you should exclude the task performing the shutdown itself.

python
1import asyncio
2
3
4async def shutdown():
5    current = asyncio.current_task()
6    tasks = [task for task in asyncio.all_tasks() if task is not current]
7
8    for task in tasks:
9        task.cancel()
10
11    await asyncio.gather(*tasks, return_exceptions=True)

This is a common pattern during graceful shutdown in services that need to stop background workers, open connections, or timers before exiting.

Using return_exceptions=True is important here. Without it, the first cancellation exception can interrupt the cleanup sequence and leave the rest of the tasks half-processed.

Cancellation Is Cooperative, Not Forced

This is the part many developers miss. A task can only react to cancellation when it reaches a point where the event loop gets control back. If a task is stuck in CPU-bound work without yielding, it will not stop promptly.

That means good async task design includes:

  • regular await points
  • cleanup in except asyncio.CancelledError
  • resource release in finally blocks when necessary

Cancellation is a protocol, not a kill signal. Well-behaved tasks cooperate with it.

Design for Safe Shutdown

In real applications, "cancel all tasks" should usually be part of a broader shutdown plan. You often want to:

  • stop accepting new work
  • cancel background tasks
  • wait for cleanup to finish
  • close network or file resources

If tasks manage sockets, files, or transactions, cancellation handling should include cleanup code rather than simply ignoring the exception. Otherwise the application may stop the coroutines while leaving external state inconsistent.

This is why cancellation-aware task code is better than trying to invent a hard kill switch. Async runtimes are built around orderly coordination, and shutdown tends to be most reliable when the tasks participate in their own cleanup.

Common Pitfalls

The most common mistake is calling .cancel() and assuming the task has already stopped. A cancellation request still needs the task to reach a cancellation point.

Another issue is forgetting to await canceled tasks. If you cancel them and exit immediately, cleanup code may never run properly.

People also sometimes call asyncio.all_tasks() and accidentally cancel the task that is trying to coordinate shutdown. Excluding the current task avoids that problem.

Summary

  • In Python asyncio, task cancellation is cooperative rather than immediate.
  • Cancel specific tasks with .cancel() and then await them with asyncio.gather(...).
  • Use asyncio.all_tasks() during shutdown when you need to cancel most tasks in the loop.
  • Exclude the current shutdown task so it can finish coordinating cleanup.
  • Well-behaved async code should expect cancellation and release resources cleanly.

Course illustration
Course illustration

All Rights Reserved.