如何提升C#批量文档检查for循环的执行性能?
优化方案
当前代码的核心性能瓶颈在于串行执行每个数据库查询操作——数据库IO属于高延迟操作,串行处理会累积所有请求的延迟,导致数据量越大耗时越长。以下是针对性的优化手段:
1. 并行异步处理(快速见效)
如果查询方法提供异步版本(如AksBelgeKontroluAsync、TckkBelgeKontroluAsync),优先采用异步并行批量处理,避免阻塞线程池:
internal async Task<DtResult> documentCheckListAsync(AksBelgeKontrolData[] belgeList, string dmUser = null) { if (string.IsNullOrEmpty(dmUser) || CurrentDomain == "nvi.local") dmUser = "MERNIS\\************"; Stopwatch sw = new Stopwatch(); sw.Start(); // 批量创建异步任务 var tasks = belgeList.Select(belgeData => belgeData.AnaBelgeTur switch { AnaBelgeTur.AksYeniBelge => GdAksYeniQueries.AksBelgeKontroluAsync(belgeData, dmUser), AnaBelgeTur.TckkYeniBelge => GdTckkYeniQueries.TckkBelgeKontroluAsync(belgeData, dmUser), _ => Task.FromResult(false) // 对应默认状态 }).ToList(); // 等待所有任务完成 var results = await Task.WhenAll(tasks); // 将结果映射回原数组 for (int i = 0; i < belgeList.Length; i++) { belgeList[i].BelgeVar = results[i]; } sw.Stop(); var test = sw.ElapsedMilliseconds; return new DtResult { ResultState = DtResultState.Ok, BelgeKontrolListesi = belgeList }; }
若没有异步版本,可使用Parallel.For实现并行处理(注意:需确保查询方法线程安全,当前场景下每个元素独立修改,无线程冲突):
internal DtResult documentCheckList(AksBelgeKontrolData[] belgeList, string dmUser = null) { if (string.IsNullOrEmpty(dmUser) || CurrentDomain == "nvi.local") dmUser = "MERNIS\\************"; Stopwatch sw = new Stopwatch(); sw.Start(); // 并行遍历数组处理每个元素 Parallel.For(0, belgeList.Length, i => { var belgeData = belgeList[i]; belgeList[i].BelgeVar = belgeData.AnaBelgeTur switch { AnaBelgeTur.AksYeniBelge => GdAksYeniQueries.AksBelgeKontrolu(belgeData, dmUser), AnaBelgeTur.TckkYeniBelge => GdTckkYeniQueries.TckkBelgeKontrolu(belgeData, dmUser), _ => false }; }); sw.Stop(); var test = sw.ElapsedMilliseconds; return new DtResult { ResultState = DtResultState.Ok, BelgeKontrolListesi = belgeList }; }
2. 批量查询优化(根本性提升)
如果可以修改查询方法的实现,建议将同类型的数据批量传入,通过一次数据库查询返回所有结果,大幅减少数据库往返次数:
首先新增批量查询方法示例:
// 示例:批量处理AksYeniBelge类型的查询 public static Dictionary<int, bool> AksBelgeKontroluBatch(AksBelgeKontrolData[] belgeDatas, string dmUser) { // 实现批量查询逻辑,以数据ID为键返回对应结果 }
然后在主方法中分组处理:
internal DtResult documentCheckList(AksBelgeKontrolData[] belgeList, string dmUser = null) { if (string.IsNullOrEmpty(dmUser) || CurrentDomain == "nvi.local") dmUser = "MERNIS\\************"; Stopwatch sw = new Stopwatch(); sw.Start(); // 按文档类型分组 var aksGroup = belgeList.Where(x => x.AnaBelgeTur == AnaBelgeTur.AksYeniBelge).ToArray(); var tckkGroup = belgeList.Where(x => x.AnaBelgeTur == AnaBelgeTur.TckkYeniBelge).ToArray(); // 批量查询每组数据 var aksResults = GdAksYeniQueries.AksBelgeKontroluBatch(aksGroup, dmUser); var tckkResults = GdTckkYeniQueries.TckkBelgeKontroluBatch(tckkGroup, dmUser); // 将结果赋值回原数组 foreach (var data in aksGroup) { data.BelgeVar = aksResults[data.Id]; // 假设Id为数据唯一标识 } foreach (var data in tckkGroup) { data.BelgeVar = tckkResults[data.Id]; } sw.Stop(); var test = sw.ElapsedMilliseconds; return new DtResult { ResultState = DtResultState.Ok, BelgeKontrolListesi = belgeList }; }
3. 细节优化
- 用
switch替代if-else:多分支判断时switch性能更优,代码可读性也更强 - 减少数组索引重复访问:循环中直接获取元素后操作,避免反复通过索引查找数组元素
- 数据库连接池配置:确保数据库连接池的
Max Pool Size参数足够,避免并行时连接耗尽
内容的提问来源于stack exchange,提问作者Büşra Güler
相关产品推荐
相关产品推荐

