如何使用HttpClient()存储来自多个异步请求的返回数据,直到所有请求完成?

时间:2015-11-18 19:34:26

标签: c# httpclient

我需要遍历一系列来自网址的数据发布请求。请求需要异步。检查所有返回已完成的最佳方法是什么,并存储该数据直到返回所有数据?更喜欢使用HttpClient()

代码段:

     HttpContent httpContent = new FormUrlEncodedContent(postData);           
     HttpResponseMessage response =  client.PostAsync("/mydata", httpContent).Result; 

     var responsecode = (int)response.StatusCode; 

     if (response.IsSuccessStatusCode)
     {
         var responseBodyAsText = await response.Content.ReadAsStringAsync();
         return responseBodyAsText;
     }
     else
     {
         return responsecode +" " +response.ReasonPhrase; 
     }

`

2 个答案:

答案 0 :(得分:1)

首先,请记住,您在这里遇到了异步问题:

 HttpContent httpContent = new FormUrlEncodedContent(postData);           

 // whoops! .Result makes this line synchronous.
 HttpResponseMessage response =  client.PostAsync("/mydata", httpContent).Result;

 var responsecode = (int)response.StatusCode; 

 if (response.IsSuccessStatusCode)
 {
     var responseBodyAsText = await response.Content.ReadAsStringAsync();
     return responseBodyAsText;
 }
 else
 {
     return responsecode +" " +response.ReasonPhrase; 
 }

接下来,由于HttpClient为您提供Task<HttpResponseMessage>,您似乎希望将所有响应(如字符串)视为Task<IEnumerable<string>>,对吧?我们可以轻松编写一个函数将Task<HttpResponseMessage>转换为Task<string>

public async Task<string> ReadResultAsync(Task<HttpResponseMessage> responseTask)
{
    var response = await responseTask;

    var responsecode = (int)response.StatusCode; 

    if (response.IsSuccessStatusCode)
    {
        var responseBodyAsText = await response.Content.ReadAsStringAsync();

        return responseBodyAsText;
    }
    else
    {
        return responsecode + " " + response.ReasonPhrase; 
    }
}

现在假设您已经收集了一些帖子数据集合,您需要将这些数据转换为字符串的异步集合,称为myData

// bear in mind, this code doesn't (necessarily) need to be in a
//  method marked "async". If you want to await on resultsTask, though,
//  it would need to be in an async method.

var tasks = myData
    .Select(x => new FormUrlEncodedContent(x)) //  IEnumerable<FormUrlEncodedContent>
    .Select(x => client.PostAsync("/mydata", x)) // IEnumerable<Task<HttpResponseMessage>>
    .Select(x => ReadResultAsync(x)) // IEnumerable<Task<string>>
    .ToArray(); // Task<string>[]

var resultsTask = Task.WhenAll(tasks); // here is Task<string[]>

答案 1 :(得分:0)

编写一个异步函数来激发你的帖子数据(我只是使用你的代码,请添加正确的错误/异常处理):

async Task<string> PostDataAsync(Dictionary<string, string> postData)
{
    var httpContent = new FormUrlEncodedContent(postData);           
    var response = await client.PostAsync("/mydata", httpContent).ConfigureAwait(false); 

    var responsecode = (int)response.StatusCode; 

    if (response.IsSuccessStatusCode)
    {
        var responseBodyAsText = await response.Content.ReadAsStringAsync().ConfigureAwait(false);
        return responseBodyAsText;
    }
    else
    {
       return responsecode +" " +response.ReasonPhrase; 
    }
}

现在,假设您有一个帖子数据列表'List&gt; postDataCollection`,然后构建您的请求

var postRequests = postDataCollection.Select(pd => PostDataAsync(pd)).ToArray();

然后等待所有人完成

var postResponses = await Task.WhenAll(postRequests);