c# - 同步使用 HttpClient 的“正确方法”是什么?
问题描述
我在“正确方式”周围使用了引号,因为我已经很清楚使用异步 API 的正确方式是让异步行为在整个调用链中传播。这不是一个选择。
我正在处理一个非常庞大且复杂的系统,该系统专门设计用于在循环中同步进行批处理。
我突然使用 HttpClient 的原因是因为之前批处理的所有数据都是从 SQL 数据库中收集的,现在我们正在添加一个 Web API 调用。
是的,我们在同步执行的循环中调用 Web API。我知道。将整个事情重写为异步只是不是一种选择。这实际上是我们想要做的。(我们尽可能减少 API 调用的数量)
实际上,我确实尝试将异步行为传播到调用链上,但后来我发现自己有 50 个文件深度变化,仍然有数百个编译器错误需要解决,并且失去了所有希望。我被打败了。
那么,回到这个问题,鉴于微软建议不要将 WebRequest 用于新开发,而是使用仅提供异步 API 的 HttpClient,我该怎么办?
这是我正在做的一些伪代码......
foreach (var thingToProcess in thingsToProcess)
{
thingToProcess.ProcessStuff(); // This makes an API call
}
如何实现 ProcessStuff()?
我的第一个实现看起来像这样
public void ProcessStuff()
{
var apiResponse = myHttpClient // this is an instance of HttpClient
.GetAsync(someUrl)
.Result;
// do some stuff with the apiResponse
}
但是有人告诉我,由于同步上下文,以这种方式调用 .Result 会导致死锁。
猜猜看,这个批处理将从 ASP.NET 控制器启动。是的,我知道,这很愚蠢。当它从 ASP.NET 运行时,它只是“批处理”一个项目而不是整个批次,但我离题了,它仍然从 ASP.NET 调用,因此我担心死锁。
那么处理这个问题的“正确方法”是什么?
解决方案
尝试以下操作:
var task = Task.Run(() => myHttpClient.GetAsync(someUrl));
task.Wait();
var response = task.Result;
仅当您无法使用async
方法时才使用它。
如 MSDN 博客中所述,此方法完全无死锁: ASP.Net–Do not use Task .Result in main context。
推荐阅读
- c++ - const string &s 和 string &s 有什么区别?
- angularjs-ng-repeat - 在angular js中使用bootstrap和ng重复对元素进行排序
- reactjs - 在 LWC 中做出反应
- r - as.date 在 Jupyter Books 的 R 脚本中不起作用
- laravel - 在godaddy服务器上的laravel 5.7中上传大文件(> 150mb)时出现“404”错误
- python - 无法从 docker 访问 Flask API 端点
- firebase - 在颤振中使用带有firebase sdk的for循环
- r - R - 创建大型图形设备(覆盖尺寸限制)
- jenkins - k8s 中的 Jenkins 不保存安装插件
- node.js - 排行榜级别系统不和谐 js