C#:使用同步、异步或与共享 HttpClient 异步时的不同结果
C#: Different results when using sync, async or async with shared HttpClient
简介
我一直在 ASP.NET Web API 工作,我在尝试调用另一个 API 时遇到了一些奇怪的交互。我已经尝试了 3 种不同的方式来使用 HttpClient,所有方式都有不同的结果。
使用 Postman 测试了所有内容,因此得到了一些结果。
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。异步 httpClient 调用
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.
(如 this SO answer 所建议)。
问题
如果有人能解释为什么这些结果如此不同,我将不胜感激 and/or 提供另一种方法来进行基本的 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
.
使用的良好信息的人
简介
我一直在 ASP.NET Web API 工作,我在尝试调用另一个 API 时遇到了一些奇怪的交互。我已经尝试了 3 种不同的方式来使用 HttpClient,所有方式都有不同的结果。
使用 Postman 测试了所有内容,因此得到了一些结果。
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。异步 httpClient 调用
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.
(如 this SO answer 所建议)。
问题
如果有人能解释为什么这些结果如此不同,我将不胜感激 and/or 提供另一种方法来进行基本的 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
.