第一次 foreach 循环后 hTTPResponse.Content.ReadAsStringAsync().Result 上的空消息
Posted
技术标签:
【中文标题】第一次 foreach 循环后 hTTPResponse.Content.ReadAsStringAsync().Result 上的空消息【英文标题】:Null message on hTTPResponse.Content.ReadAsStringAsync().Result after 1st foreach loop 【发布时间】:2019-07-17 22:58:30 【问题描述】:在 foreach 循环中调用 HttpClient getAsync 时出现空结果消息的问题。
我需要使用对象列表进行迭代,以便通过 HttpClient 调用 API。在第一个循环之后,HttpResponseMessage 的 result() 出现空消息。
我试过 CacheControl.NoCache = true。它不工作。
public async Task<List<Common.ProgressResponse>> RunAsync()
List<Response> ListOfResponses = new List<Responses>();
try
_client.BaseAddress = new Uri([URL]);
_client.DefaultRequestHeaders.Accept.Clear();
_client.DefaultRequestHeaders.Clear();
_client.DefaultRequestHeaders.CacheControl = new CacheControlHeaderValue() NoCache = true ;
_client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
_client.DefaultRequestHeaders.Add([KEY], [VALUE]);
ListOfResponses = await SomeFunction();
catch (Exception ex)
//Exceptions here...
return ListOfResponses;
private async Task<List<ListOfResponses>> SomeFunction()
List<Response> responses = new List<Response>();
string aPISuffix = string.Format("0/1", [APISUFFIX1], [APISUFFIX2]);
foreach (Object obj in ListOfObject)
_client.DefaultRequestHeaders.Add("Param1", obj.Param1);
if (!string.IsNullOrEmpty(obj.Param2))
_client.DefaultRequestHeaders.Add("Param2", obj.Param2);
Response response = new Response();
/*This is where the issue is .begin.*/
HttpResponseMessage hTTPResponse = await _client.GetAsync(aPISuffix).ConfigureAwait(false);
string result = hTTPResponse.Content.ReadAsStringAsync().Result;
/*This is where the issue is .end.*/
if (hTTPResponse.IsSuccessStatusCode)
response = [Code here...]
//Codes here...
responses.Add(response);
return responses;
On: '字符串结果 = hTTPResponse.Content.ReadAsStringAsync().Result;' 我希望结果消息在循环通过 ListOfObjects 时具有值。
【问题讨论】:
你为什么到处都用await
,却突然在那一行上用.Result
?
您应该在阅读内容之前检查 httpResponse 状态码。你可能会看到一些惊喜。我看不到 httpclient 是如何启动的,但我会小心重置默认标头,而是尝试在每个请求的基础上指定它们,以避免多个请求相互冲突跨度>
因为调用函数都是异步的...
@ESG httpClient 是类中的静态全局变量。该类使用 using() 语句进行实例化。
@praetorean 也要小心静态 httpclients。如果您将此类注册为单例,那么您的 DNS 条目将变得陈旧。
【参考方案1】:
更新:每条评论
首先,我通常会尽量避免将 .Result 用于任务。我也不认为添加缓存标头是问题,因为您正在进行服务器到服务器的调用。
我经常做的一件事是在尝试阅读之前评估响应。我也更喜欢使用 HttpRequestMessage 以便我可以管理它的处置。
这是一个演示如何调用的简单示例:
using System;
using System.Net.Http;
using System.Threading.Tasks;
namespace Testing
class Program
static void Main(string[] args)
TestAsync().Wait();
static async Task TestAsync()
var urls = new string[]
"https://***.com/questions/57084989/null-message-on-httpresponse-content-readasstringasync-result-after-1st-foreac",
"https://***.com/users/2025711/rogala"
;
using (var httpClient = new HttpClient())
foreach (var url in urls)
using (var request = new HttpRequestMessage(HttpMethod.Get, url))
Console.WriteLine($"Request: url".PadLeft(5,'*').PadRight(5, '*'));
var response = await httpClient.SendAsync(request)
.ConfigureAwait(false);
if (response.IsSuccessStatusCode)
var body = await response.Content.ReadAsStringAsync()
.ConfigureAwait(false);
Console.WriteLine($"body.LengthEnvironment.NewLine");
else
Console.WriteLine($"*Bad request: response.StatusCode");
Console.ReadKey();
要记住的另一件事是插槽耗尽。如果此代码在服务器上运行,那么一旦您的服务获得一些负载,您将遇到套接字耗尽。我强烈建议使用HttpClientFactory 来处理 HttpClients。
关于内容字符串为空的原因,可能是因为服务器没有返回可能是服务器问题的内容。服务器可能还限制了您,导致没有内容。我建议查看Polly 来处理某些响应代码。
【讨论】:
什么?这并不能真正回答问题,您只是修复了一些小错误。如果您声称使用 .Result 是问题,请解释原因。 不,我展示的模式确实有效。正如评论中提到的,在检查结果之前,您不应尝试阅读正文。此外,此模式的不同之处在于生成并发送新的 HttpRequestMessage 与调用 get。最后,我在这里可能是错的,但是服务器到服务器的调用不需要缓存。 该评论应该是您答案的第一部分。如果您从用户部分阅读此答案,则不清楚如何或为什么会解决此问题【参考方案2】:解决了...我在 foreach() 循环中移动了 .DefaultRequestHeaders 值。 我怀疑它们在每次循环迭代时都会堆积起来。我必须在 GetAsync() 之前清除它们并设置它们
此处更新代码:
public async Task<List<Common.ProgressResponse>> RunAsync()
List<Response> ListOfResponses = new List<Responses>();
try
_client.BaseAddress = new Uri([URL]);
ListOfResponses = await SomeFunction();
catch (Exception ex)
//Exceptions here...
return ListOfResponses;
private async Task<List<ListOfResponses>> SomeFunction()
List<Response> responses = new List<Response>();
string aPISuffix = string.Format("0/1", [APISUFFIX1], [APISUFFIX2]);
foreach (Object obj in ListOfObject)
/*Moved Code .begin.*/
_client.DefaultRequestHeaders.Accept.Clear();
_client.DefaultRequestHeaders.Clear();
_client.DefaultRequestHeaders.CacheControl = new CacheControlHeaderValue() NoCache = true ;
_client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
_client.DefaultRequestHeaders.Add([KEY], [VALUE]);
/*Moved Code .end.*/
_client.DefaultRequestHeaders.Add("Param1", obj.Param1);
if (!string.IsNullOrEmpty(obj.Param2))
_client.DefaultRequestHeaders.Add("Param2", obj.Param2);
Response response = new Response();
HttpResponseMessage hTTPResponse = await _client.GetAsync(aPISuffix).ConfigureAwait(false);
if (hTTPResponse.IsSuccessStatusCode)
string result = hTTPResponse.Content.ReadAsStringAsync().Result;
response = [Code here...]
//Codes here...
responses.Add(response);
return responses;
【讨论】:
这正是我喜欢使用 HttpRequestMessage 的原因。必须清除标题似乎有点奇怪。恕我直言 - 通过将代码添加到消息中,代码更清晰。单元测试也更容易。以上是关于第一次 foreach 循环后 hTTPResponse.Content.ReadAsStringAsync().Result 上的空消息的主要内容,如果未能解决你的问题,请参考以下文章
PHP foreach循环里面调用函数,需要等函数返回成功才能进入下一次循环,怎么弄呢?