asyncio.create_task: Đạo diễn các nhiệm vụ Python không chặn!
Python

asyncio.create_task: Đạo diễn các nhiệm vụ Python không chặn!

Author

Admin System

@root

Ngày xuất bản

21 Mar, 2026

Lượt xem

4 Lượt

"asyncio_create_task"

Chào các 'dev-er' tương lai của Gen Z! Anh Creyt lại 'on air' đây, hôm nay chúng ta sẽ 'phá đảo' một khái niệm nghe hơi 'hàn lâm' nhưng thực ra 'chill phết' trong Python: asyncio.create_task.

1. asyncio.create_task: Nó là 'cái vẹo' gì và để làm gì?

"Thôi ngay cái kiểu 'chạy tuần tự' đi các em!" Đó là câu nói mà asyncio thì thầm vào tai chúng ta. Giống như các em đang lướt TikTok, xem YouTube, và chat với crush cùng lúc vậy. Các em không có 3 cái não để làm 3 việc đó thực sự song song đâu, mà là các em chuyển đổi qua lại giữa chúng cực kỳ nhanh và hiệu quả, đúng không? Đó chính là cái 'vibe' của asyncio.

asyncio trong Python giúp chúng ta viết code 'bất đồng bộ' (asynchronous) và 'đồng thời' (concurrently) – tức là, thay vì đợi một việc hoàn thành 100% rồi mới làm việc khác, ta có thể 'đá' việc đang đợi sang một bên và làm việc khác ngay lập tức. Cụ thể, khi một tác vụ nào đó đang 'await' (chờ đợi) một thứ gì đó (ví dụ: chờ dữ liệu từ mạng về, chờ đọc file, chờ database trả lời), thì thay vì đứng 'chôn chân' đợi, asyncio sẽ 'nhảy' sang làm việc khác.

Thế còn asyncio.create_task? Nó chính là 'thằng quản lý' hay 'tay đạo diễn' tài ba của chúng ta. Khi các em có một 'coroutine' (tức là một hàm async def – một kịch bản cần diễn), các em dùng create_task để nói với asyncio (cái 'sân khấu' event loop): "Ê, đạo diễn! Tôi có cái kịch bản này, anh cứ xếp lịch cho nó diễn đi, không cần phải đợi tôi diễn xong cái này mới được diễn cái kia đâu. Cứ đưa nó vào 'danh sách chờ' đi, khi nào có thời gian trống thì gọi nó lên sân khấu!"

Nói cách khác, create_task sẽ lên lịch cho một coroutine chạy trên 'vòng lặp sự kiện' (event loop) của asyncio mà không chặn việc thực thi của coroutine hiện tại. Nó trả về một đối tượng Task mà sau này các em có thể 'await' nó để lấy kết quả hoặc xử lý ngoại lệ.

2. Code Ví Dụ Minh Họa Rõ Ràng, Chuẩn Kiến Thức

Để các em dễ hình dung, hãy xem ví dụ này. Chúng ta có 3 'diễn viên' đang 'đợi' để 'diễn' các vai của mình. Nếu chạy tuần tự, sẽ phải đợi từng người một. Nhưng với asyncio.create_task, họ sẽ được 'lên lịch' và chạy 'xen kẽ' nhau, tối ưu thời gian chờ.

import asyncio
import time

async def say_hello(name, delay):
    """Một coroutine giả lập công việc tốn thời gian (I/O)."""
    print(f"[{time.time():.2f}] 🎬 Anh {name} ơi, chuẩn bị diễn! Đợi {delay}s nha...")
    await asyncio.sleep(delay) # Giả lập I/O: chờ mạng, database, file...
    print(f"[{time.time():.2f}] ✅ Anh {name} đã diễn xong vai của mình.")
    return f"Kết thúc vai của {name}"

async def main():
    """Hàm chính điều phối các tác vụ."""
    print(f"[{time.time():.2f}] Bắt đầu buổi diễn chính...")

    # Dùng asyncio.create_task để 'lên lịch' cho các diễn viên
    task_an = asyncio.create_task(say_hello("An", 3)) # Lên lịch cho An, đợi 3s
    task_binh = asyncio.create_task(say_hello("Bình", 1)) # Lên lịch cho Bình, đợi 1s
    task_cuc = asyncio.create_task(say_hello("Cúc", 2)) # Lên lịch cho Cúc, đợi 2s

    print(f"[{time.time():.2f}] 💡 Đã lên lịch cho các diễn viên. Sân khấu đang chờ...")

    # Chờ tất cả các task hoàn thành. Đây là lúc 'đạo diễn' thu thập kết quả.
    # asyncio.gather sẽ chờ tất cả các task được truyền vào hoàn thành
    results = await asyncio.gather(task_an, task_binh, task_cuc)

    print(f"[{time.time():.2f}] 👏 Buổi diễn kết thúc! Kết quả: {results}")

if __name__ == "__main__":
    asyncio.run(main()) # Khởi động 'sân khấu' (event loop) và chạy buổi diễn

Giải thích: Khi chạy đoạn code trên, các em sẽ thấy: An, Bình, Cúc không đợi nhau. Bình xong trước (1s), rồi đến Cúc (2s), và cuối cùng là An (3s). main function không bị 'đứng hình' mà ngay lập tức sau khi create_task đã in ra dòng "Đã lên lịch..." và chỉ await asyncio.gather khi cần chờ kết quả của tất cả.

Illustration

3. Mẹo (Best Practices) để Ghi Nhớ và Dùng Thực Tế

  • Đừng quên 'await' Task: Khi các em create_task, nó chỉ là 'lên lịch' thôi. Để đảm bảo task đó chạy xong, lấy kết quả, hoặc bắt được lỗi của nó, các em phải await nó (hoặc await một nhóm task bằng asyncio.gather). Nếu không, nó sẽ chạy 'lang thang như con ghẻ không ai thèm ngó tới', có thể hoàn thành mà các em không biết, hoặc tệ hơn là lỗi mà không ai xử lý.
  • create_task vs. await trực tiếp:
    • await some_async_func(): Hàm main (hoặc coroutine hiện tại) sẽ đứng yên chờ some_async_func hoàn thành. Dùng khi các em cần kết quả ngay lập tức hoặc không muốn chạy song song với các tác vụ khác.
    • task = asyncio.create_task(some_async_func()): Hàm main tiếp tục chạy ngay lập tức. some_async_func được đẩy vào 'hàng đợi' để asyncio xử lý khi có thời gian. Dùng khi các em muốn 'khởi động' nhiều tác vụ cùng lúc và 'thu thập' kết quả sau này (thường là với asyncio.gather).
  • Sử dụng asyncio.gather cho nhiều Tasks: Đây là cách 'xịn sò' nhất để chờ một loạt các task hoàn thành và thu thập kết quả của chúng một cách hiệu quả. Nó giống như việc 'thu hoạch' tất cả các thành quả sau khi 'gieo trồng' một loạt các nhiệm vụ vậy.
  • Xử lý lỗi (Error Handling): Một task có thể 'fail' (nổi loạn) và ném ra ngoại lệ. Hãy dùng try...except khi await một task (hoặc gather các task) để bắt và xử lý lỗi kịp thời.

4. Ứng Dụng Thực Tế

asyncio.create_taskasyncio nói chung là 'key' cho các ứng dụng cần xử lý hàng tá request cùng lúc mà không bị 'nghẽn cổ chai':

  • Web Servers (FastAPI, Sanic, Aiohttp): Khi hàng ngàn người dùng truy cập website cùng lúc, mỗi request có thể được xử lý như một task riêng biệt. create_task giúp server không bị 'đứng hình' khi một request đang chờ database hay một API bên thứ ba trả về.
  • API Clients: Khi các em cần gọi nhiều API khác nhau để lấy dữ liệu (ví dụ: lấy thông tin người dùng từ server A, lấy lịch sử mua hàng từ server B, lấy khuyến mãi từ server C). Thay vì đợi từng cái một, create_task giúp gọi tất cả cùng lúc và chờ kết quả. Siêu nhanh!
  • Real-time Applications: Chat servers, game servers. Khi có hàng trăm người chơi gửi tin nhắn hay hành động, mỗi sự kiện có thể được biến thành một task để xử lý mà không làm chậm hệ thống.
  • Data Scraping/Crawling: Khi các em muốn 'hốt' dữ liệu từ hàng ngàn trang web. create_task giúp các em gửi hàng loạt yêu cầu HTTP đi cùng lúc thay vì đợi từng trang tải xong.

5. Thử Nghiệm và Nên Dùng Cho Case Nào

Anh Creyt đã 'chinh chiến' với asyncio đủ lâu để đúc kết ra rằng:

  • Nên dùng khi: Các em có các tác vụ 'I/O-bound' – tức là các tác vụ mà phần lớn thời gian là 'chờ đợi' (chờ mạng, chờ đĩa, chờ database). Đây chính là 'sân chơi' của asyncio. Nó giống như việc các em đặt đồ ăn online, thay vì ngồi nhìn màn hình đợi, các em có thể làm việc khác trong lúc chờ shipper tới. asyncio sẽ 'nhắc' các em khi đồ ăn đến.
  • Tránh dùng khi: Các tác vụ 'CPU-bound' – tức là các tác vụ cần nhiều sức mạnh tính toán của CPU (ví dụ: xử lý hình ảnh phức tạp, tính toán khoa học nặng). asyncio chạy trên một luồng (thread) duy nhất, nên nếu một task 'ngốn' CPU quá lâu, nó sẽ 'block' toàn bộ event loop, khiến mọi tác vụ khác cũng bị đình trệ. Đối với các case này, hãy nghĩ đến multiprocessing để tận dụng nhiều core CPU.

Lời khuyên từ anh Creyt: Hãy coi asyncio.create_task như một 'phó đạo diễn' đắc lực, giúp các em dàn xếp các cảnh quay một cách linh hoạt. Nắm vững nó, các em sẽ viết được những ứng dụng Python 'mượt mà' và 'thần tốc' hơn rất nhiều đó! Cứ thử nghiệm đi, 'code is life', mà 'life is async' mà, phải không?

Thuộc Series: Python

Bài giảng này được tự động xuất bản ngẫu nhiên từ thư viện kiến thức. Đừng quên đón xem các Từ khoá Hướng Dẫn tiếp theo nhé!

#tech #cyberpunk #laravel
Chỉnh sửa bài viết

Bình luận (0)

Vui lòng Đăng Nhập để Bình luận

Hỗ trợ Markdown cơ bản
Nguyễn Văn A
1 ngày trước

Tính năng này đỉnh quá ad ơi, chờ mãi mới thấy một blog Tiếng Việt có UI/UX xịn như vầy!