C#:与共享 HttpClient 使用同步、异步或异步时的结果不同



简介

我一直在 Web API 中工作 ASP.NET 在尝试调用另一个 API 时遇到了一些奇怪的交互。我尝试了 3 种不同的方法来使用 HttpClient,但结果都不同。
使用邮递员测试了所有内容,因此得出了一些结果。

1. 同步 HttpClient 调用

private static string GetAPI(string url)
{
using (HttpClient client = new HttpClient())
{
client.BaseAddress = new Uri(url);
client.DefaultRequestHeaders.Accept.Clear();
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
client.DefaultRequestHeaders.Add("x-api-key", "SomeSecretApiKey");
HttpResponseMessage response = client.GetAsync(url).Result;
string contents = response.Content.ReadAsStringAsync().Result;
if (response.IsSuccessStatusCode)
{
return contents;
}
}
return null;
}

结果

确实有效,但我想使用async

2. 异步 http客户端调用

private static async Task<string> GetAPI(string url)
{
using (HttpClient client = new HttpClient())
{
client.BaseAddress = new Uri(url);
client.DefaultRequestHeaders.Accept.Clear();
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
client.DefaultRequestHeaders.Add("x-api-key", "SomeSecretApiKey");
HttpResponseMessage response = await client.GetAsync(url);
string contents = await response.Content.ReadAsStringAsync();
if (response.IsSuccessStatusCode)
{
return contents;
}
}
return null;
}

结果

不工作。不会超出HttpResponseMessage response = await client.GetAsync(url);线,因为从来没有回应?

3. 使用共享的 HttpClient 异步 httpClient 调用

private static readonly HttpClient client = new HttpClient();
private static async Task<string> GetAPI(string url)
{
client.BaseAddress = new Uri(url);
client.DefaultRequestHeaders.Accept.Clear();
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
client.DefaultRequestHeaders.Add("x-api-key", "SomeSecretApiKey");
HttpResponseMessage response = await client.GetAsync(url);
string contents = await response.Content.ReadAsStringAsync();
if (response.IsSuccessStatusCode)
{
return contents;
}
return null;
}

结果

工作一次。然后将抛出错误:System.AggregateException: One or more errors occurred. ---> System.InvalidOperationException: This instance has already started one or more requests. Properties can only be modified before sending the first request.(如此 SO 答案所示(。

问题

如果有人能解释为什么这些结果如此不同和/或提供一种进行基本HttpClient调用的替代方法(仍然想使用async(,我将不胜感激。

@Igor在我的第二个示例中通知了我死锁问题。
所以我目前使用这样的HttpClient(async(:

private static async Task<string> GetAPI(string url)
{
// TODO: Use a shared instance of HttpClient
using (HttpClient client = new HttpClient())
{
client.BaseAddress = new Uri(url);
client.DefaultRequestHeaders.Accept.Clear();
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
client.DefaultRequestHeaders.Add("x-api-key", "SomeSecretApiKey");
var jsonString = await client.GetStringAsync(url).ConfigureAwait(false);
return jsonString;
}
}

虽然有些事情已经说清楚了,但整个问题还没有得到解答。因此,我不会接受这个答案,但要感谢那些为我提供有关使用HttpClient的良好信息的人。

最新更新