ASP.NET Core 6递归树形函数中Parallel.ForEachAsync能否保证层级保存顺序?
问题解答
是的,你必须改用串行的foreach循环,原因如下:
1. Parallel.ForEachAsync无法保证层级内的保存顺序
Parallel.ForEachAsync会并行调度多个子节点的保存任务,这些任务的执行顺序完全由线程调度器决定,和原树形结构中node.children的顺序没有任何关联,直接违反你要求的层级顺序保存规则。
2. 存在线程安全隐患
你使用的List<ResponseBase<BatchRowData>>不是线程安全集合,多个并行任务同时调用allResponses.Add(response)时,会引发数据竞争,可能导致元素丢失、集合损坏或重复添加等问题——当前看似正常只是因为并发量不够高,隐患始终存在。
3. 递归并行无实际收益
数据库保存是IO密集型操作,异步方法await DBGate.PostAsync已经能释放线程到线程池处理其他请求,并行处理同一层级子节点不仅不会显著提升效率,反而可能给数据库带来额外的并发压力,甚至触发数据库的并发限制。
修改后的代码示例
private async Task<List<ResponseBase<BatchRowData>>> SaveDepartments(DepartmentTree node, string parentUnitGuid, List<ResponseBase<BatchRowData>> allResponses) { if (parentUnitGuid == null) { return allResponses; } // 改用串行foreach,严格保证子节点的保存顺序与原树形结构一致 foreach (var child in node.children) { ResponseBase<BatchRowData> response = new ResponseBase<BatchRowData>(); //...do something Unit unit = new Unit(); unit.SerialNum = child.data.DepartmentNumber; unit.UnitName = child.data.DepartmentName; unit.ParentUnitGuid = parentUnitGuid; string unitGuid = await DBGate.PostAsync<string>("organization/SaveUnit", unit); if (unitGuid != null) { response.IsSuccess = true; response.ResponseData.ReturnGuid = unitGuid; await SaveDepartments(child, unitGuid, allResponses); } else { response.IsSuccess = false; response.ResponseData.ErrorDescription = "Failed to Save"; } allResponses.Add(response); } return allResponses; }
内容的提问来源于stack exchange,提问作者Zinger
相关产品推荐
相关产品推荐

