我previously posted关于将HTTPClient
与async / await一起使用的问题。现在,我试图弄清楚如何以这样的方式实现这一点,即实际上使Post调用同时执行,同时仍然能够处理结果HttpResponseMessage
。
这就是我想出的。然而,作为一个等待/异步的菜鸟,我仍然不确定我是否正确地做了这个。有人可以验证这是正确的方法......或者至少是正确的方式。
public async Task ProcessAsync() {
//Query lists
List<Member> list = dbContext.Users.Where(u => u.IsMember).ToList();
//Add members to mailing list through web service
await AddMembersAsync(list);
}
private async Task AddMembersAsync(List<Member> members) {
using(var _client = new HttpClient()) {
//Initialize Http Client
...
var responses = await Task.WhenAll(members.Select(x => PostMemberAsync(x,_client)));
await Task.WhenAll(responses.Select(r => ProcessResponseAsync(r,client)));
}
}
private async Task<HttpResponseMessage> PostMemberAsync(Member member, HttpClient client) {
var jss = new JavaScriptSerializer();
var content = jss.Serialize(new MemberPost() {
email_address = member.email,
...
});
return await client.PostAsync("uri",new StringContent(content, Encoding.UTF8, "application/json"));
}
private async Task ProcessResponsesAsync(HttpResponseMessage response, HttpClient client) {
if(response.IsSuccessStatusCode) {
var responseText = await response.Content.ReadAsStringAsync();
var jss = new JavaScriptSerializer();
var userid = jss.Deserialize<MemberResponse>(responseText);
//Store mailing user's id
...
}
response.Dispose();
}
这对我来说似乎是正确的。但是,我有一个小问题。我需要将每个HttpResponseMessage
绑定到为其创建消息的成员。我当前的代码只返回Task,但响应消息不包含指向用户的链接。 (我发布的服务返回特定于服务的ID。我需要跟踪每个用户的ID,以便我在成员ID和服务ID之间建立链接。)
我是否要求将响应消息中的id链接到成员使得使用上面的代码变得不现实,或者有没有办法以某种方式将成员作为任务结果的一部分返回?
答案 0 :(得分:1)
我建议不要试一试,所以请小心,但我会替换这两行:
var responses = await Task.WhenAll(members.Select(x => PostMemberAsync(x,_client)));
await Task.WhenAll(responses.Select(r => ProcessResponseAsync(r,client)));
用这个:
await Task.WhenAll(members.Select(async x =>
{
var response = await PostMemberAsync(x, _client);
await ProcessResponseAsync(response, client, x);
}));
当然,您需要通过参数Member
来增强ProcessResponseAsync答案 1 :(得分:0)
我需要将每个HttpResponseMessage绑定到为其创建消息的成员。
在进行异步编程时,我觉得避免副作用很有用。换句话说,如果您有一个计算或确定某事的方法,则从该方法返回该值,而不是将其保存在某个成员变量中。
private async Task<MemberResponse> ProcessResponseAsync(HttpResponseMessage response, HttpClient client)
{
using (response)
{
if(response.IsSuccessStatusCode)
{
var responseText = await response.Content.ReadAsStringAsync();
var jss = new JavaScriptSerializer();
var userid = jss.Deserialize<MemberResponse>(responseText);
return userid;
}
else
{ ... }
}
}
添加一个小帮助方法,您的调用代码变得非常干净:
private async Task<HttpResponseMessage> ProcessMemberAsync(Member member, HttpClient client)
{
var response = await PostMemberAsync(member, client);
return await ProcessResponseAsync(response, client);
}
private async Task AddMembersAsync(List<Member> members)
{
using(var client = new HttpClient())
{
... // Initialize HttpClient
var responses = await Task.WhenAll(members.Select(x => ProcessMemberAsync(x, client)));
for (int i = 0; i != members.Count; ++i)
{
var member = members[i];
var response = responses[i];
...
}
}
}