此方法使用.Result
。这是否意味着任务不会异步运行?是否需要重构才能使令牌的每个请求真正异步?
public async Task<string> ReturnDataFromUrlAsync(List<List<KeyValuePair<string, string>>> listOfPostData)
{
string allTokens = "";
var client = new HttpClient
{
BaseAddress = new Uri("http://localhost:23081")
};
var downloadTasksQuery = listOfPostData.Select(postData =>
{
var content = new FormUrlEncodedContent(postData);
HttpResponseMessage response = client.PostAsync("/Token", content).Result;
var responseBodyAsText = response.Content.ReadAsStringAsync();
return responseBodyAsText;
});
List<Task<string>> downloadTasks = downloadTasksQuery.ToList();
while (downloadTasks.Count > 0)
{
Task<string> firstFinishedTask = await Task.WhenAny(downloadTasks);
downloadTasks.Remove(firstFinishedTask);
// Await the completed task.
string content = await firstFinishedTask;
allTokens = allTokens + content;
}
return allTokens;
}
答案 0 :(得分:2)
所以目前这个电话:
HttpResponseMessage response = client.PostAsync("/Token", content).Result;
将导致调用线程停止并等待结果。如果在client.PostAsync
之前放置await关键字,它将导致调用线程返回调用者并在操作完成后恢复。由于这是在linq查询中完成的,因此您需要使lambda表达式异步,如下所示:
var downloadTasksQuery = listOfPostData.Select(async postData =>
{
var content = new FormUrlEncodedContent(postData);
HttpResponseMessage response = await client.PostAsync("/Token", content);
var responseBodyAsText = await response.Content.ReadAsStringAsync();
return responseBodyAsText;
});
在lambda表达式中追加async关键字将推断返回类型必须是Task类型,并且我们也选择类型为IEnumerable<Task<string>>
的字符串
我也注意到了这一点:
var responseBodyAsText = response.Content.ReadAsStringAsync();
我认为混淆的原因是因为这个语句实际上是返回一个Task而不是一个字符串(如果你使用var
,请注意你的名字)
我们可以再次在response.Content
之前放置await关键字,并自动推断返回键。然后我们可以在linq查询中选择字符串,而不是Task<string>