You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Django中@sync_to_async与异步视图未并行执行问题求助

问题原因与解决方案

你的代码中两个被@sync_to_async装饰的函数串行执行,导致总耗时为7秒,核心原因是sync_to_async默认的thread_sensitive=True参数限制。

当thread_sensitive=True时,asgiref会将所有同步任务调度到同一个线程中执行(为兼容Django的线程敏感操作,比如数据库连接上下文),因此asyncio.gather无法实现并行,只能按顺序执行两个任务(2秒+5秒=7秒)。

修改方案

将@sync_to_async装饰器的thread_sensitive参数设为False,让每个同步任务在独立线程中运行,即可实现并行:

import time
import asyncio

from asgiref.sync import sync_to_async
from django.http import HttpResponse

from movies.models import Movie
from stories.models import Story

# 添加thread_sensitive=False参数
@sync_to_async(thread_sensitive=False)
def get_movies_async():
    print('prepare to get the movies...')
    time.sleep(2)
    qs = Movie.objects.all()
    print('got all the movies')

# 添加thread_sensitive=False参数
@sync_to_async(thread_sensitive=False)
def get_stories_async():
    print('prepare to get the stories...')
    time.sleep(5)
    qs = Story.objects.all()
    print('got all the stories')

async def main_view_async(request):
    start_time = time.time()
    await asyncio.gather(get_movies_async(), get_stories_async())
    total = (time.time() - start_time)
    print("total: ", total)
    return HttpResponse('async!')

补充说明

2020年的教程中sync_to_async默认的thread_sensitive值为False,但后续asgiref版本(从3.0左右开始)将默认值改为True,以此优化Django数据库连接的复用和线程安全。如果你的同步任务确实需要访问Django的数据库或其他线程敏感资源,建议保持thread_sensitive=True,同时通过手动创建独立线程池的方式实现并行:

# 自定义线程池
from concurrent.futures import ThreadPoolExecutor

custom_executor = ThreadPoolExecutor(max_workers=2)

@sync_to_async(executor=custom_executor)
def get_movies_async():
    # ... 原代码不变

@sync_to_async(executor=custom_executor)
def get_stories_async():
    # ... 原代码不变

这种方式既保证了线程敏感操作的安全性,又能让任务并行执行。

内容的提问来源于stack exchange,提问作者Ivan

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.03 14:05:13