如何通过Task.ContinueWith调用异步方法?哪种方案更优?
四种异步依赖调用方案的优劣分析
先明确场景:我们需要先调用API获取产品,再根据产品的CategoryId调用另一个API获取分类,四个方案里最优的是完全不使用ContinueWith的分步await实现,下面逐个拆解分析:
方案1:使用await await
这个方案能正常运行,但嵌套的await await写法非常不直观,而且ContinueWith属于早期异步编程API,用它会让代码结构变得冗余复杂,可读性差,后续维护成本高。
方案2:使用await加Task.Result
这个方案存在严重问题:在ContinueWith的委托里调用.Result会同步阻塞线程,直接丢失了异步编程非阻塞的核心优势。如果在UI线程或带有SynchronizationContext的环境中运行,甚至可能触发死锁,绝对不推荐使用。
方案3:使用Unwrap加await
Unwrap能把嵌套的Task<Task<ProductCategory>>展开为Task<ProductCategory>,比方案1的可读性稍好,但依然依赖ContinueWith。ContinueWith默认的任务调度器可能和当前上下文不一致,容易引发难以排查的线程问题,代码结构也不如直接分步await清晰。
方案4:完全不使用ContinueWith,分步await
这是现代C#异步编程的标准写法:
var product = await httpClient.GetFromJsonAsync<Product>("https://apiexample.com/api/products/1234"); category = await httpClient.GetFromJsonAsync<ProductCategory>($"https://apiexample.com/api/categories/{product?.CategoryId}");
代码逻辑一目了然,可读性极强,维护成本低。同时await会自动处理上下文同步(比如保留UI线程上下文),异常处理也更简单(可直接用try-catch包裹整个流程),完全符合异步编程的最佳实践,是四个方案里的最优解。
内容的提问来源于stack exchange,提问作者Jossean Yamil
相关产品推荐
相关产品推荐

