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

使用Task.WhenAll()触发SqlDataReader 409冲突,为何改.Result可解决?

问题解析:两种异步写法导致409冲突的原因

核心区别在于两种写法的任务执行方式不同:第一种是并行执行所有异步任务,第二种是串行执行,这直接导致了是否触发服务端的并发冲突限制。

第一种写法(触发409)

return await Task.WhenAll(servicesResponse);

Task.WhenAll会同时启动所有由contractServices.Select(async cs => ...)生成的异步任务,也就是多个AddContractBillableConceptsToServices方法会并行执行。如果这个方法内部涉及对同一资源(比如数据库记录、共享缓存、或有并发限制的服务)的操作,并行请求就会触发服务端的冲突检测,返回409 "Conflict"错误——这通常是因为服务端不允许同一资源被多个请求同时修改或操作。

第二种写法(正常运行)

return servicesResponse.Select(t => t.Result);

这里的Select是延迟执行的,当枚举返回的IEnumerable时,会逐个等待每个Task完成:每次调用t.Result都会阻塞当前线程,直到这个异步任务执行完毕,才会处理下一个Task。相当于把原本的并行执行改成了串行执行,避免了多个请求同时操作同一资源的情况,自然不会触发409冲突。

额外注意

第二种写法虽然解决了冲突,但存在潜在问题:在异步方法里直接调用Task.Result可能导致死锁(比如在有SynchronizationContext的环境中,如ASP.NET旧版)。如果要保持异步且串行执行,更合理的写法是用循环逐个await:

var result = new List<ContractServiceResponse>();
foreach (var task in servicesResponse)
{
    result.Add(await task);
}
return result;

这样既保持了异步非阻塞,又能串行执行任务,避免冲突的同时也规避了死锁风险。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.04 23:25:19