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

Individual await与Task.WhenAll执行效率无差异,我的理解有误吗?

问题分析:为什么并行执行存储过程没看到性能提升?

你有两个返回相同结果的方法,代码如下:

public static async Task<IEnumerable<RiskDetails>> ExecuteSqlStoredProcedureSelect<T>(IEnumerable<AccountInfo> linkedAccounts, string connectionString, string storedProcedure, int connTimeout = 10) { 
    var responseList = new List<RiskDetails>(); 
    using (IDbConnection conn = new SqlConnection(connectionString)) { 
        foreach (var account in linkedAccounts) { 
            var enumResults = await conn.QueryAsync<RiskDetails>(storedProcedure, new { 
                UserID = account.UserID, 
                CasinoID = account.CasinoID, 
                GamingServerID = account.GamingServerID, 
                AccountNo = account.AccountNumber, 
                Group = account.GroupCode, 
                EmailAddress = account.USEMAIL 
            }, commandType: CommandType.StoredProcedure); 
            if (enumResults != null) 
                foreach (var response in enumResults) 
                    responseList.Add(response); 
        } 
    } 
    return responseList; 
} 

public static async Task<IEnumerable<RiskDetails>> ExecuteSqlStoredProcedureSelectParallel<T>(IEnumerable<AccountInfo> linkedAccounts, string connectionString, string storedProcedure, int connTimeout = 10) { 
    List<Task<IEnumerable<RiskDetails>>> tasks = new List<Task<IEnumerable<RiskDetails>>>(); 
    var responseList = new List<RiskDetails>(); 
    using (IDbConnection conn = new SqlConnection(connectionString)) { 
        conn.Open(); 
        foreach (var account in linkedAccounts) { 
            var enumResults = conn.QueryAsync<RiskDetails>(storedProcedure, new { 
                UserID = account.UserID, 
                CasinoID = account.CasinoID, 
                GamingServerID = account.GamingServerID, 
                AccountNo = account.AccountNumber, 
                Group = account.GroupCode, 
                EmailAddress = account.USEMAIL 
            }, commandType: CommandType.StoredProcedure, commandTimeout: 0); 
            //add task 
            tasks.Add(enumResults); 
        } 
        //await and get results 
        var results = await Task.WhenAll(tasks); 
        foreach (var value in results) 
            foreach (var riskDetail in value) 
                responseList.Add(riskDetail); 
    } 
    return responseList; 
} 

你对两个方法的执行流程理解如下:

对ExecuteSqlStoredProcedureSelect的理解

  • 执行账户#1的查询
  • 等待查询#1的结果
  • 接收查询#1的结果
  • 执行账户#2的查询
  • 等待查询#2的结果
  • 依此类推

对ExecuteSqlStoredProcedureSelectParallel的理解

  • 将所有任务添加至集合实例
  • 调用Task.WhenAll,开始执行所有账户#n的查询
  • 查询相对并行地在SQL Server上执行
  • 所有查询执行完成后,Task.WhenAll返回

你的理解存在的关键错误

你对第一个方法的流程理解是完全正确的,它确实是串行执行每个账户的存储过程调用,完成一个再启动下一个。

但对第二个方法的理解有核心误区:你在同一个数据库连接上启动多个异步查询,这并不会真正并行执行。

SQL Server的单个连接是串行化处理请求的——即使你用异步方法提交多个查询,它们也会在同一个连接上排队执行,一个完成后才会处理下一个。也就是说,你的ExecuteSqlStoredProcedureSelectParallel方法看起来是并行提交任务,但实际上这些任务在数据库端还是串行执行的,和第一个方法没有本质区别,自然看不到性能提升。


怎么改才能真正实现并行?

要让存储过程调用真正并行执行,你需要为每个任务创建独立的数据库连接:

public static async Task<IEnumerable<RiskDetails>> ExecuteSqlStoredProcedureSelectParallel<T>(IEnumerable<AccountInfo> linkedAccounts, string connectionString, string storedProcedure, int connTimeout = 10) { 
    var tasks = linkedAccounts.Select(async account => {
        using (var conn = new SqlConnection(connectionString)) {
            await conn.OpenAsync();
            return await conn.QueryAsync<RiskDetails>(storedProcedure, new { 
                UserID = account.UserID, 
                CasinoID = account.CasinoID, 
                GamingServerID = account.GamingServerID, 
                AccountNo = account.AccountNumber, 
                Group = account.GroupCode, 
                EmailAddress = account.USEMAIL 
            }, commandType: CommandType.StoredProcedure, commandTimeout: 0);
        }
    });

    var results = await Task.WhenAll(tasks);
    return results.SelectMany(r => r);
}

这样每个查询都使用独立的连接,SQL Server可以同时处理多个请求,才能真正体现并行的性能优势。

不过要注意:并行执行会增加数据库的负载,你需要根据数据库的承载能力控制并行度(比如用SemaphoreSlim限制并发连接数),避免压垮数据库。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.29 07:36:05