【发布时间】:2021-11-04 08:27:58
【问题描述】:
我有一个 .NET Core Web 应用,一旦调用了一个 Web 方法(即 Test()),就会调用另一个远程 api。
基本上,我是这样做的(这是一个 POST 示例,在 Web 方法 Test() 中调用):
public T PostRead<T>(string baseAddress, string url, out bool succeded, object entity = null)
{
T returnValue = default(T);
succeded = false;
try
{
using (HttpClient client = new HttpClient())
{
client.DefaultRequestHeaders.Add("Authorization", MyApiKey);
HttpResponseMessage res = null;
string json = JsonConvert.SerializeObject(entity);
var body = new StringContent(json, UnicodeEncoding.UTF8, "application/json");
var task = Task.Run(() => client.PostAsync($"{baseAddress}/{url}", body));
task.Wait();
res = task.Result;
succeded = res.IsSuccessStatusCode;
if (succeded)
{
returnValue = JsonConvert.DeserializeObject<T>(res.Content.ReadAsStringAsync().Result);
}
else
{
Log($"PostRead failed, error: {JsonConvert.SerializeObject(res)}");
}
}
}
catch (Exception ex)
{
Log($"PostRead error: {baseAddress}/{url} entity: {JsonConvert.SerializeObject(entity)}");
}
return returnValue;
}
问题是:如果我的 Web App 中的 Test() 被并行调用 10 次,对远程服务器的 POST 请求是并行调用还是串行调用?
因为如果它们会被串行调用,最后一个会占用前一个的时间,这不是我想要的。
事实上,当我有大量的请求时,我经常会收到消息连接尝试失败,因为连接的一方在一段时间后没有正确响应,或者建立连接失败,因为连接的主机失败回应。
【问题讨论】:
-
我能问一下你为什么不完全异步吗?为什么要打扰
Task.Run而不是GetAwaiter().GetResult()?如果你的PostRead方法是异步的,你可以并行调用PostRead和Task.WaitAll。另外,HttpClient不应该在整个应用程序中真正注入和重用(您只需操作一次 defaultheaders 和 api 键) -
请阅读:You're (probably still) using HttpClient wrong and it is destabilizing your software。然后:摆脱
Task.Run并正确使用async和await,你只是无缘无故地浪费线程,而不是让ASP.NET Core 有效地管理它们。至于实际问题,这里没有lock,所以我不知道是什么让你认为他们会串行运行 -
@Camilo Terevinto 使用它是否正确? stackoverflow.com/a/31102831/365251
-
否 - 任何时候看到
new HttpClient都是错误的,除非在最简单的应用程序中每分钟/小时发生一次。 HttpClient 实例需要重用。至于异步部分,是的,这个例子很好 -
要回答你的问题,除非你在实现中这样做,否则这里没有异步运行。至于您的错误,您需要小心,因为即使以您当前的速度,您也可能会受到限制。我怀疑同时运行的东西会帮助你当前的错误。此外,如前所述,还有更好的方法来使用 httpclient,即 IHttpClientFactory,并让它全部使用
async
标签: c# httpclient asp.net-core-2.2